Added credentials manager and updated omni drivers.
This change: 1. Adds credmanager service which handles credentials for AWS drivers. 2. Adds support for managing multiple AWS accounts through use of credmanager. Each account is mapped to a single project in keystone. 3. Adds support for multiple AZs by running one nova-compute and cinder-volume process per AZ. 4. Improves support for AWS networking in neutron. 5. Also, made few stability fixes in GCP and Azure drivers. Change-Id: I0f87005a924423397db659ab754caaa6cde90274
This commit is contained in:
0
creds_manager/credsmgr/wsgi/__init__.py
Normal file
0
creds_manager/credsmgr/wsgi/__init__.py
Normal file
219
creds_manager/credsmgr/wsgi/common.py
Normal file
219
creds_manager/credsmgr/wsgi/common.py
Normal file
@@ -0,0 +1,219 @@
|
||||
# Copyright 2017 Platform9 Systems.
|
||||
# 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.
|
||||
"""Utility methods for working with WSGI servers."""
|
||||
|
||||
import webob.dec
|
||||
import webob.exc
|
||||
|
||||
from credsmgr.api.controllers import api_version_request
|
||||
from credsmgr import exception
|
||||
|
||||
SUPPORTED_CONTENT_TYPES = ('application/json')
|
||||
|
||||
SUPPORTED_ACCEPT_TYPES = ('application/json')
|
||||
|
||||
|
||||
class Request(webob.Request):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Request, self).__init__(*args, **kwargs)
|
||||
self.support_api_request_version = False
|
||||
if not hasattr(self, 'api_version_request'):
|
||||
self.api_version_request = api_version_request.APIVersionRequest()
|
||||
|
||||
def set_api_version_request(self, url):
|
||||
"""Set API version request based on the request header information.
|
||||
"""
|
||||
if 'v1' in url:
|
||||
self.api_version_request = 'v1'
|
||||
|
||||
def get_content_type(self):
|
||||
"""Determine content type of the request body.
|
||||
|
||||
Does not do any body introspection, only checks header
|
||||
"""
|
||||
if "Content-Type" not in self.headers:
|
||||
return None
|
||||
|
||||
allowed_types = SUPPORTED_CONTENT_TYPES
|
||||
content_type = self.content_type
|
||||
|
||||
if content_type not in allowed_types:
|
||||
raise exception.InvalidContentType(content_type=content_type)
|
||||
|
||||
return content_type
|
||||
|
||||
def best_match_content_type(self):
|
||||
"""Determine the requested response content-type."""
|
||||
if 'credsmgr.best_content_type' not in self.environ:
|
||||
# Calculate the best MIME type
|
||||
content_type = None
|
||||
|
||||
# Check URL path suffix
|
||||
parts = self.path.rsplit('.', 1)
|
||||
if len(parts) > 1:
|
||||
possible_type = 'application/' + parts[1]
|
||||
if possible_type in SUPPORTED_CONTENT_TYPES:
|
||||
content_type = possible_type
|
||||
|
||||
if not content_type:
|
||||
# FIXME: Implement Accept best match algorithm when needed
|
||||
# content_type = self.accept.best_match(
|
||||
# SUPPORTED_CONTENT_TYPES)
|
||||
content_type = 'application/json'
|
||||
|
||||
self.environ['credsmgr.best_content_type'] = content_type
|
||||
|
||||
return self.environ['credsmgr.best_content_type']
|
||||
|
||||
def best_match_language(self):
|
||||
"""Determines best available locale from the Accept-Language header.
|
||||
|
||||
:returns: the best language match or None if the 'Accept-Language'
|
||||
header was not available in the request.
|
||||
"""
|
||||
# if not self.accept_language:
|
||||
# return None
|
||||
# FIXME: TO be fixed when language support is added
|
||||
return None
|
||||
|
||||
|
||||
class Application(object):
|
||||
"""Base WSGI application wrapper. Subclasses need to implement __call__."""
|
||||
|
||||
@classmethod
|
||||
def factory(cls, global_config, **local_config):
|
||||
"""Used for paste app factories in paste.deploy config files.
|
||||
|
||||
Any local configuration (that is, values under the [app:APPNAME]
|
||||
section of the paste config) will be passed into the `__init__` method
|
||||
as kwargs.
|
||||
|
||||
A hypothetical configuration would look like:
|
||||
|
||||
[app:wadl]
|
||||
latest_version = 1.3
|
||||
paste.app_factory = credsmgr.api.fancy_api:Wadl.factory
|
||||
|
||||
which would result in a call to the `Wadl` class as
|
||||
|
||||
import credsmgr.api.fancy_api
|
||||
fancy_api.Wadl(latest_version='1.3')
|
||||
|
||||
You could of course re-implement the `factory` method in subclasses,
|
||||
but using the kwarg passing it shouldn't be necessary.
|
||||
|
||||
"""
|
||||
return cls(**local_config)
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
r"""Subclasses will probably want to implement __call__ like this:
|
||||
|
||||
@webob.dec.wsgify(RequestClass=Request)
|
||||
def __call__(self, req):
|
||||
# Any of the following objects work as responses:
|
||||
|
||||
# Option 1: simple string
|
||||
res = 'message\n'
|
||||
|
||||
# Option 2: a nicely formatted HTTP exception page
|
||||
res = exc.HTTPForbidden(explanation='Nice try')
|
||||
|
||||
# Option 3: a webob Response object (in case you need to play with
|
||||
# headers, or you want to be treated like an iterable)
|
||||
res = Response();
|
||||
res.app_iter = open('somefile')
|
||||
|
||||
# Option 4: any wsgi app to be run next
|
||||
res = self.application
|
||||
|
||||
# Option 5: you can get a Response object for a wsgi app, too, to
|
||||
# play with headers etc
|
||||
res = req.get_response(self.application)
|
||||
|
||||
# You can then just return your response...
|
||||
return res
|
||||
# ... or set req.response and return None.
|
||||
req.response = res
|
||||
|
||||
See the end of http://pythonpaste.org/webob/modules/dec.html
|
||||
for more info.
|
||||
|
||||
"""
|
||||
raise NotImplementedError('You must implement __call__')
|
||||
|
||||
|
||||
class Middleware(Application):
|
||||
"""Base WSGI middleware.
|
||||
|
||||
These classes require an application to be
|
||||
initialized that will be called next. By default the middleware will
|
||||
simply call its wrapped app, or you can override __call__ to customize its
|
||||
behavior.
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def factory(cls, global_config, **local_config):
|
||||
"""Used for paste app factories in paste.deploy config files.
|
||||
|
||||
Any local configuration (that is, values under the [filter:APPNAME]
|
||||
section of the paste config) will be passed into the `__init__` method
|
||||
as kwargs.
|
||||
|
||||
A hypothetical configuration would look like:
|
||||
|
||||
[filter:analytics]
|
||||
redis_host = 127.0.0.1
|
||||
paste.filter_factory = credsmgr.api.analytics:Analytics.factory
|
||||
|
||||
which would result in a call to the `Analytics` class as
|
||||
|
||||
import credsmgr.api.analytics
|
||||
analytics.Analytics(app_from_paste, redis_host='127.0.0.1')
|
||||
|
||||
You could of course re-implement the `factory` method in subclasses,
|
||||
but using the kwarg passing it shouldn't be necessary.
|
||||
|
||||
"""
|
||||
|
||||
def _factory(app):
|
||||
return cls(app, **local_config)
|
||||
|
||||
return _factory
|
||||
|
||||
def __init__(self, application):
|
||||
self.application = application
|
||||
|
||||
def process_request(self, req):
|
||||
"""Called on each request.
|
||||
|
||||
If this returns None, the next application down the stack will be
|
||||
executed. If it returns a response then that response will be returned
|
||||
and execution will stop here.
|
||||
|
||||
"""
|
||||
return None
|
||||
|
||||
def process_response(self, response):
|
||||
"""Do whatever you'd like to the response."""
|
||||
return response
|
||||
|
||||
@webob.dec.wsgify(RequestClass=Request)
|
||||
def __call__(self, req):
|
||||
response = self.process_request(req)
|
||||
if response:
|
||||
return response
|
||||
response = req.get_response(self.application)
|
||||
return self.process_response(response)
|
||||
Reference in New Issue
Block a user