Fixed H404 and related pep8 errors
This commit is contained in:
@@ -37,7 +37,8 @@ class VersionNegotiationFilter(wsgi.Middleware):
|
||||
super(VersionNegotiationFilter, self).__init__(app)
|
||||
|
||||
def process_request(self, req):
|
||||
"""
|
||||
"""Process WSGI requests.
|
||||
|
||||
If there is a version identifier in the URI, simply
|
||||
return the correct API controller, otherwise, if we
|
||||
find an Accept: header, process it
|
||||
@@ -104,10 +105,11 @@ class VersionNegotiationFilter(wsgi.Middleware):
|
||||
return None
|
||||
|
||||
def _match_version_string(self, subject, req):
|
||||
"""
|
||||
Given a subject string, tries to match a major and/or
|
||||
minor version number. If found, sets the api.major_version
|
||||
and api.minor_version environ variables.
|
||||
"""Do version matching.
|
||||
|
||||
Given a subject string, tries to match a major and/or minor version
|
||||
number. If found, sets the api.major_version and api.minor_version
|
||||
environ variables.
|
||||
|
||||
Returns True if there was a match, false otherwise.
|
||||
|
||||
|
||||
@@ -24,10 +24,7 @@ from senlin.common import wsgi
|
||||
|
||||
|
||||
class API(wsgi.Router):
|
||||
|
||||
"""
|
||||
WSGI router for Cluster v1 ReST API requests.
|
||||
"""
|
||||
'''WSGI router for Cluster v1 ReST API requests.'''
|
||||
|
||||
def __init__(self, conf, **local_conf):
|
||||
self.conf = conf
|
||||
|
||||
@@ -25,6 +25,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
class ActionData(object):
|
||||
'''All required data fields for an action.'''
|
||||
|
||||
PARAMS = (
|
||||
NAME, TARGET, ACTION,
|
||||
) = (
|
||||
@@ -55,9 +56,8 @@ class ActionData(object):
|
||||
|
||||
|
||||
class ActionController(object):
|
||||
"""
|
||||
WSGI controller for Actions in Senlin v1 API
|
||||
"""
|
||||
'''WSGI controller for Actions in Senlin v1 API.'''
|
||||
|
||||
# Define request scope (must match what is in policy.json)
|
||||
REQUEST_SCOPE = 'actions'
|
||||
|
||||
@@ -120,9 +120,8 @@ class ActionController(object):
|
||||
|
||||
|
||||
def create_resource(options):
|
||||
"""
|
||||
Actions factory method.
|
||||
"""
|
||||
'''Actions factory method.'''
|
||||
|
||||
return wsgi.Resource(ActionController(options),
|
||||
wsgi.JSONRequestDeserializer(),
|
||||
serializers.JSONResponseSerializer())
|
||||
|
||||
@@ -20,10 +20,10 @@ from senlin.rpc import client as rpc_client
|
||||
|
||||
|
||||
class BuildInfoController(object):
|
||||
"""
|
||||
WSGI controller for BuildInfo in Senlin v1 API
|
||||
'''WSGI controller for BuildInfo in Senlin v1 API.
|
||||
Returns build information for current app
|
||||
"""
|
||||
'''
|
||||
|
||||
# Define request scope (must match what is in policy.json)
|
||||
REQUEST_SCOPE = 'build_info'
|
||||
|
||||
@@ -43,9 +43,8 @@ class BuildInfoController(object):
|
||||
|
||||
|
||||
def create_resource(options):
|
||||
"""
|
||||
BuildInfo factory method.
|
||||
"""
|
||||
'''BuildInfo factory method.'''
|
||||
|
||||
deserializer = wsgi.JSONRequestDeserializer()
|
||||
serializer = serializers.JSONResponseSerializer()
|
||||
return wsgi.Resource(BuildInfoController(options), deserializer,
|
||||
|
||||
@@ -31,9 +31,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InstantiationData(object):
|
||||
"""
|
||||
The data accompanying a PUT or POST request to create or update a cluster.
|
||||
"""
|
||||
'''The data accompanying a PUT/POST request to create/update a cluster.'''
|
||||
|
||||
PARAMS = (
|
||||
attr.CLUSTER_NAME, attr.CLUSTER_SIZE, attr.CLUSTER_PROFILE,
|
||||
attr.CLUSTER_TAGS, attr.CLUSTER_TIMEOUT
|
||||
@@ -69,10 +68,8 @@ class InstantiationData(object):
|
||||
|
||||
|
||||
class ClusterController(object):
|
||||
"""
|
||||
WSGI controller for clusters resource in Senlin v1 API
|
||||
Implements the API actions
|
||||
"""
|
||||
'''WSGI controller for clusters resource in Senlin v1 API.'''
|
||||
|
||||
# Define request scope (must match what is in policy.json)
|
||||
REQUEST_SCOPE = 'clusters'
|
||||
|
||||
@@ -112,9 +109,8 @@ class ClusterController(object):
|
||||
|
||||
@util.policy_enforce
|
||||
def create(self, req, body):
|
||||
"""
|
||||
Create a new cluster
|
||||
"""
|
||||
'''Create a new cluster.'''
|
||||
|
||||
data = InstantiationData(body)
|
||||
|
||||
action = self.rpc_client.cluster_create(req.context, data.name(),
|
||||
@@ -126,9 +122,7 @@ class ClusterController(object):
|
||||
|
||||
@util.policy_enforce
|
||||
def get(self, req, cluster_id):
|
||||
"""
|
||||
Gets detailed information for a cluster
|
||||
"""
|
||||
'''Gets detailed information for a cluster.'''
|
||||
|
||||
cluster = self.rpc_client.cluster_get(req.context,
|
||||
cluster_id)
|
||||
@@ -139,9 +133,8 @@ class ClusterController(object):
|
||||
|
||||
@util.policy_enforce
|
||||
def update(self, req, cluster_id, body):
|
||||
"""
|
||||
Update an existing cluster with new parameters
|
||||
"""
|
||||
'''Update an existing cluster with new parameters.'''
|
||||
|
||||
data = InstantiationData(body)
|
||||
|
||||
self.rpc_client.cluster_update(req.context,
|
||||
@@ -164,9 +157,8 @@ class ClusterController(object):
|
||||
|
||||
|
||||
def create_resource(options):
|
||||
"""
|
||||
Clusters resource factory method.
|
||||
"""
|
||||
'''Clusters resource factory method.'''
|
||||
|
||||
return wsgi.Resource(ClusterController(options),
|
||||
wsgi.JSONRequestDeserializer(),
|
||||
serializers.JSONResponseSerializer())
|
||||
|
||||
@@ -27,9 +27,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InstantiationData(object):
|
||||
"""
|
||||
The data accompanying a PUT or POST request to create or update a cluster.
|
||||
"""
|
||||
'''The data accompanying a PUT/POST request to create/update a node.'''
|
||||
|
||||
PARAMS = (
|
||||
NAME, CLUSTER_ID, PROFILE_ID, ROLE, TAGS,
|
||||
@@ -69,9 +67,7 @@ class InstantiationData(object):
|
||||
|
||||
|
||||
class NodeController(object):
|
||||
'''
|
||||
WSGI controller for nodes resource in Senlin v1 API
|
||||
'''
|
||||
'''WSGI controller for nodes resource in Senlin v1 API.'''
|
||||
|
||||
REQUEST_SCOPE = 'nodes'
|
||||
|
||||
@@ -149,9 +145,8 @@ class NodeController(object):
|
||||
|
||||
|
||||
def create_resource(options):
|
||||
"""
|
||||
Nodes resource factory method.
|
||||
"""
|
||||
'''Nodes resource factory method.'''
|
||||
|
||||
return wsgi.Resource(NodeController(options),
|
||||
wsgi.JSONRequestDeserializer(),
|
||||
serializers.JSONResponseSerializer())
|
||||
|
||||
@@ -26,9 +26,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PolicyTypeController(object):
|
||||
'''
|
||||
WSGI controller for policy types resource in Senlin v1 API
|
||||
'''
|
||||
'''WSGI controller for policy types resource in Senlin v1 API.'''
|
||||
# Define request scope (must match what is in policy.json)
|
||||
REQUEST_SCOPE = 'policy_types'
|
||||
|
||||
@@ -62,9 +60,8 @@ class PolicyTypeController(object):
|
||||
|
||||
|
||||
def create_resource(options):
|
||||
'''
|
||||
Policy type resource factory method.
|
||||
'''
|
||||
'''Policy type resource factory method.'''
|
||||
|
||||
return wsgi.Resource(PolicyTypeController(options),
|
||||
wsgi.JSONRequestDeserializer(),
|
||||
serializers.JSONResponseSerializer())
|
||||
|
||||
@@ -27,9 +27,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ProfileTypeController(object):
|
||||
'''
|
||||
WSGI controller for profile types resource in Senlin v1 API
|
||||
'''
|
||||
'''WSGI controller for profile types resource in Senlin v1 API.'''
|
||||
|
||||
# Define request scope (must match what is in policy.json)
|
||||
REQUEST_SCOPE = 'profile_types'
|
||||
|
||||
@@ -47,9 +46,7 @@ class ProfileTypeController(object):
|
||||
|
||||
@util.policy_enforce
|
||||
def spec(self, req, type_name):
|
||||
'''
|
||||
Gets the interface schema for a specified profile type.
|
||||
'''
|
||||
'''Gets the interface schema for a specified profile type.'''
|
||||
spec = self.rpc_client.profile_type_spec(req.context, type_name)
|
||||
if not spec:
|
||||
raise exc.HTTPInternalServerError()
|
||||
@@ -58,9 +55,8 @@ class ProfileTypeController(object):
|
||||
|
||||
@util.policy_enforce
|
||||
def template(self, req, type_name):
|
||||
'''
|
||||
Gets the template representation for a specified profile type.
|
||||
'''
|
||||
'''Gets the template representation for a specified profile type.'''
|
||||
|
||||
tmpl = self.rpc_client.profile_type_template(req.context, type_name)
|
||||
if not tmpl:
|
||||
raise exc.HTTPInternalServerError()
|
||||
@@ -69,9 +65,8 @@ class ProfileTypeController(object):
|
||||
|
||||
|
||||
def create_resource(options):
|
||||
'''
|
||||
Profiles resource factory method.
|
||||
'''
|
||||
'''Profiles resource factory method.'''
|
||||
|
||||
return wsgi.Resource(ProfileTypeController(options),
|
||||
wsgi.JSONRequestDeserializer(),
|
||||
serializers.JSONResponseSerializer())
|
||||
|
||||
@@ -27,9 +27,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ProfileData(object):
|
||||
"""
|
||||
The data accompanying a PUT or POST request to create or update a cluster.
|
||||
"""
|
||||
'''The data accompanying a PUT/POST request to create/update a profile.'''
|
||||
|
||||
PARAMS = (
|
||||
NAME, SPEC, TYPE, PERMISSION, TAGS,
|
||||
@@ -67,8 +65,7 @@ class ProfileData(object):
|
||||
|
||||
|
||||
class ProfileController(object):
|
||||
'''WSGI controller for profiles resource in Senlin v1 API.
|
||||
'''
|
||||
'''WSGI controller for profiles resource in Senlin v1 API.'''
|
||||
|
||||
# Define request scope (must match what is in policy.json)
|
||||
REQUEST_SCOPE = 'profiles'
|
||||
@@ -158,9 +155,8 @@ class ProfileController(object):
|
||||
|
||||
|
||||
def create_resource(options):
|
||||
"""
|
||||
Profiles resource factory method.
|
||||
"""
|
||||
'''Profiles resource factory method.'''
|
||||
|
||||
return wsgi.Resource(ProfileController(options),
|
||||
wsgi.JSONRequestDeserializer(),
|
||||
serializers.JSONResponseSerializer())
|
||||
|
||||
@@ -22,10 +22,7 @@ import webob.dec
|
||||
|
||||
|
||||
class Controller(object):
|
||||
|
||||
"""
|
||||
A controller that produces information on the senlin API versions.
|
||||
"""
|
||||
'''A controller that produces information on the senlin API versions.'''
|
||||
|
||||
def __init__(self, conf):
|
||||
self.conf = conf
|
||||
|
||||
@@ -34,17 +34,15 @@ def do_db_version():
|
||||
|
||||
|
||||
def do_db_sync():
|
||||
"""
|
||||
Place a database under migration control and upgrade,
|
||||
"""Place a database under migration control and upgrade,
|
||||
creating first if necessary.
|
||||
"""
|
||||
api.db_sync(api.get_engine(), CONF.command.version)
|
||||
|
||||
|
||||
def purge_deleted():
|
||||
"""
|
||||
Remove database records that have been previously soft deleted
|
||||
"""
|
||||
"""Remove database records that have been previously soft deleted."""
|
||||
|
||||
utils.purge_deleted(CONF.command.age, CONF.command.granularity)
|
||||
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ from webob import exc
|
||||
|
||||
|
||||
class KeystonePasswordAuthProtocol(object):
|
||||
"""
|
||||
Alternative authentication middleware that uses username and password
|
||||
"""Alternative authentication middleware that uses username and password
|
||||
to authenticate against Keystone instead of validating existing auth token.
|
||||
The benefit being that you no longer require admin/service token to
|
||||
authenticate users.
|
||||
|
||||
@@ -123,8 +123,7 @@ for group, opts in list_opts():
|
||||
|
||||
|
||||
def _get_deployment_flavor():
|
||||
"""
|
||||
Retrieve the paste_deploy.flavor config item, formatted appropriately
|
||||
"""Retrieve the paste_deploy.flavor config item, formatted appropriately
|
||||
for appending to the application name.
|
||||
"""
|
||||
flavor = cfg.CONF.paste_deploy.flavor
|
||||
@@ -132,8 +131,7 @@ def _get_deployment_flavor():
|
||||
|
||||
|
||||
def _get_deployment_config_file():
|
||||
"""
|
||||
Retrieve the deployment_config_file config item, formatted as an
|
||||
"""Retrieve the deployment_config_file config item, formatted as an
|
||||
absolute pathname.
|
||||
"""
|
||||
config_path = cfg.CONF.find_file(
|
||||
@@ -145,8 +143,7 @@ def _get_deployment_config_file():
|
||||
|
||||
|
||||
def load_paste_app(app_name=None):
|
||||
"""
|
||||
Builds and returns a WSGI app from a paste config file.
|
||||
"""Builds and returns a WSGI app from a paste config file.
|
||||
|
||||
We assume the last config file specified in the supplied ConfigOpts
|
||||
object is the paste config file.
|
||||
|
||||
@@ -24,10 +24,11 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RequestContext(context.RequestContext):
|
||||
"""
|
||||
Stores information about the security context under which the user
|
||||
'''Stores information about the security context.
|
||||
|
||||
The context encapsulates information related to the user
|
||||
accesses the system, as well as additional request information.
|
||||
"""
|
||||
'''
|
||||
|
||||
def __init__(self, auth_token=None, auth_token_info=None,
|
||||
username=None, user_id=None, password=None, is_admin=None,
|
||||
@@ -37,10 +38,10 @@ class RequestContext(context.RequestContext):
|
||||
region_name=None, roles=None,
|
||||
read_only=False, show_deleted=False,
|
||||
request_id=None, **kwargs):
|
||||
"""
|
||||
'''Initializer of request context.
|
||||
:param kwargs: Extra arguments that might be present, but we ignore
|
||||
because they possibly came in from older rpc messages.
|
||||
"""
|
||||
'''
|
||||
super(RequestContext, self).__init__(auth_token=auth_token,
|
||||
user=username,
|
||||
tenant=tenant,
|
||||
@@ -124,16 +125,15 @@ class ContextMiddleware(wsgi.Middleware):
|
||||
super(ContextMiddleware, self).__init__(app)
|
||||
|
||||
def make_context(self, *args, **kwargs):
|
||||
"""
|
||||
Create a context with the given arguments.
|
||||
"""
|
||||
'''Create a context with the given arguments.'''
|
||||
|
||||
return self.ctxcls(*args, **kwargs)
|
||||
|
||||
def process_request(self, req):
|
||||
"""
|
||||
Extract any authentication information in the request and
|
||||
'''Extract any authentication information in the request and
|
||||
construct an appropriate context from it.
|
||||
"""
|
||||
'''
|
||||
|
||||
headers = req.headers
|
||||
environ = req.environ
|
||||
try:
|
||||
@@ -179,9 +179,8 @@ class ContextMiddleware(wsgi.Middleware):
|
||||
|
||||
|
||||
def ContextMiddleware_filter_factory(global_conf, **local_conf):
|
||||
"""
|
||||
Factory method for paste.deploy
|
||||
"""
|
||||
'''Factory method for paste.deploy'''
|
||||
|
||||
conf = global_conf.copy()
|
||||
conf.update(local_conf)
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
#
|
||||
# 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
|
||||
# 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.
|
||||
# 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 oslo_utils import strutils
|
||||
|
||||
@@ -17,10 +16,10 @@ from senlin.common.i18n import _
|
||||
|
||||
|
||||
def extract_bool(subject):
|
||||
'''
|
||||
Convert any true/false string to its corresponding boolean value,
|
||||
'''Convert any true/false string to its corresponding boolean value,
|
||||
regardless of case.
|
||||
'''
|
||||
|
||||
if str(subject).lower() not in ('true', 'false'):
|
||||
raise ValueError(_('Unrecognized value "%(value)s", acceptable '
|
||||
'values are: true, false.') % {'value': subject})
|
||||
|
||||
@@ -114,8 +114,7 @@ def get_bind_addr(conf, default_port=None):
|
||||
|
||||
|
||||
def get_socket(conf, default_port):
|
||||
"""
|
||||
Bind socket to bind ip:port in conf
|
||||
'''Bind socket to bind ip:port in conf
|
||||
|
||||
note: Mostly comes from Swift with a few small changes...
|
||||
|
||||
@@ -124,7 +123,8 @@ def get_socket(conf, default_port):
|
||||
|
||||
:returns : a socket object as returned from socket.listen or
|
||||
ssl.wrap_socket if conf specifies cert_file
|
||||
"""
|
||||
'''
|
||||
|
||||
bind_addr = get_bind_addr(conf, default_port)
|
||||
|
||||
# TODO(jaypipes): eventlet's greened socket module does not actually
|
||||
@@ -179,13 +179,12 @@ class Server(object):
|
||||
self.running = True
|
||||
|
||||
def start(self, application, conf, default_port):
|
||||
"""
|
||||
Run a WSGI server with the given application.
|
||||
'''Run a WSGI server with the given application.
|
||||
|
||||
:param application: The application to run in the WSGI server
|
||||
:param conf: a cfg.ConfigOpts object
|
||||
:param default_port: Port to bind to if none is specified in conf
|
||||
"""
|
||||
'''
|
||||
def kill_children(*args):
|
||||
"""Kills the entire process group."""
|
||||
self.LOG.error(_LE('SIGTERM received'))
|
||||
@@ -194,9 +193,8 @@ class Server(object):
|
||||
os.killpg(0, signal.SIGTERM)
|
||||
|
||||
def hup(*args):
|
||||
"""
|
||||
Shuts down the server(s), but allows running requests to complete
|
||||
"""
|
||||
# Shuts down the server(s), but allows running requests to complete
|
||||
|
||||
self.LOG.error(_LE('SIGHUP received'))
|
||||
signal.signal(signal.SIGHUP, signal.SIG_IGN)
|
||||
os.killpg(0, signal.SIGHUP)
|
||||
@@ -291,25 +289,24 @@ class Server(object):
|
||||
|
||||
|
||||
class Middleware(object):
|
||||
"""
|
||||
Base WSGI middleware wrapper. 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.
|
||||
"""
|
||||
'''Base WSGI middleware wrapper.
|
||||
|
||||
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.
|
||||
'''
|
||||
|
||||
def __init__(self, application):
|
||||
self.application = application
|
||||
|
||||
def process_request(self, req):
|
||||
"""
|
||||
Called on each request.
|
||||
'''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):
|
||||
@@ -326,10 +323,9 @@ class Middleware(object):
|
||||
|
||||
|
||||
class Debug(Middleware):
|
||||
"""
|
||||
Helper class that can be inserted into any WSGI application chain
|
||||
'''Helper class that can be inserted into any WSGI application chain
|
||||
to get information about the request and response.
|
||||
"""
|
||||
'''
|
||||
|
||||
@webob.dec.wsgify
|
||||
def __call__(self, req):
|
||||
@@ -350,10 +346,8 @@ class Debug(Middleware):
|
||||
|
||||
@staticmethod
|
||||
def print_generator(app_iter):
|
||||
"""
|
||||
Iterator that prints the contents of a wrapper string iterator
|
||||
when iterated.
|
||||
"""
|
||||
# Iterator that prints the contents of a wrapper string iterator
|
||||
# when iterated.
|
||||
print(("*" * 40) + " BODY")
|
||||
for part in app_iter:
|
||||
sys.stdout.write(part)
|
||||
@@ -367,13 +361,10 @@ def debug_filter(app, conf, **local_conf):
|
||||
|
||||
|
||||
class Router(object):
|
||||
"""
|
||||
WSGI middleware that maps incoming requests to WSGI apps.
|
||||
"""
|
||||
'''WSGI middleware that maps incoming requests to WSGI apps.'''
|
||||
|
||||
def __init__(self, mapper):
|
||||
"""
|
||||
Create a router for the given routes.Mapper.
|
||||
'''Create a router for the given routes.Mapper.
|
||||
|
||||
Each route in `mapper` must specify a 'controller', which is a
|
||||
WSGI app to call. You'll probably want to specify an 'action' as
|
||||
@@ -394,27 +385,30 @@ class Router(object):
|
||||
# {path_info:.*} parameter so the target app can be handed just that
|
||||
# section of the URL.
|
||||
mapper.connect(None, "/v1.0/{path_info:.*}", controller=BlogApp())
|
||||
"""
|
||||
'''
|
||||
|
||||
self.map = mapper
|
||||
self._router = routes.middleware.RoutesMiddleware(self._dispatch,
|
||||
self.map)
|
||||
|
||||
@webob.dec.wsgify
|
||||
def __call__(self, req):
|
||||
"""
|
||||
Route the incoming request to a controller based on self.map.
|
||||
'''Route the incoming request to a controller based on self.map.
|
||||
|
||||
If no match, return a 404.
|
||||
"""
|
||||
'''
|
||||
|
||||
return self._router
|
||||
|
||||
@staticmethod
|
||||
@webob.dec.wsgify
|
||||
def _dispatch(req):
|
||||
"""
|
||||
Called by self._router after matching the incoming request to a route
|
||||
and putting the information into req.environ. Either returns 404
|
||||
or the routed WSGI app's response.
|
||||
"""
|
||||
'''Called by self._router after matching the incoming request to
|
||||
a route and putting the information into req.environ.
|
||||
|
||||
Either returns 404 or the routed WSGI app's response.
|
||||
'''
|
||||
|
||||
match = req.environ['wsgiorg.routing_args'][1]
|
||||
if not match:
|
||||
return webob.exc.HTTPNotFound()
|
||||
@@ -477,11 +471,11 @@ def is_json_content_type(request):
|
||||
|
||||
class JSONRequestDeserializer(object):
|
||||
def has_body(self, request):
|
||||
"""
|
||||
Returns whether a Webob.Request object will possess an entity body.
|
||||
'''Returns whether a Webob.Request object will possess an entity body.
|
||||
|
||||
:param request: Webob.Request object
|
||||
"""
|
||||
'''
|
||||
|
||||
if request.content_length > 0 and is_json_content_type(request):
|
||||
return True
|
||||
|
||||
@@ -507,8 +501,7 @@ class JSONRequestDeserializer(object):
|
||||
|
||||
|
||||
class Resource(object):
|
||||
"""
|
||||
WSGI app that handles (de)serialization and controller dispatch.
|
||||
'''WSGI app that handles (de)serialization and controller dispatch.
|
||||
|
||||
Reads routing information supplied by RoutesMiddleware and calls
|
||||
the requested action method upon its deserializer, controller,
|
||||
@@ -522,9 +515,10 @@ class Resource(object):
|
||||
arguments that represent the keys returned by the Deserializer. They
|
||||
may raise a webob.exc exception or return a dict, which will be
|
||||
serialized by requested content type.
|
||||
"""
|
||||
'''
|
||||
|
||||
def __init__(self, controller, deserializer, serializer=None):
|
||||
"""
|
||||
"""Initializer.
|
||||
:param controller: object that implement methods created by routes lib
|
||||
:param deserializer: object that supports webob request deserialization
|
||||
through controller-like actions
|
||||
@@ -647,7 +641,6 @@ def translate_exception(exc, locale):
|
||||
|
||||
|
||||
class BasePasteFactory(object):
|
||||
|
||||
"""A base class for paste app and filter factories.
|
||||
|
||||
Sub-classes must override the KEY class attribute and provide
|
||||
@@ -684,7 +677,6 @@ class BasePasteFactory(object):
|
||||
|
||||
|
||||
class AppFactory(BasePasteFactory):
|
||||
|
||||
"""A Generic paste.deploy app factory.
|
||||
|
||||
This requires senlin.app_factory to be set to a callable which returns a
|
||||
|
||||
@@ -113,8 +113,7 @@ def _paginate_query(context, query, model, limit=None, marker=None,
|
||||
|
||||
|
||||
def soft_delete_aware_query(context, *args, **kwargs):
|
||||
"""
|
||||
Object query helper that accounts for the `show_deleted` field.
|
||||
"""Object query helper that accounts for the `show_deleted` field.
|
||||
|
||||
:param show_deleted: if True, overrides context's show_deleted field.
|
||||
"""
|
||||
|
||||
@@ -139,8 +139,7 @@ class Node(BASE, SenlinBase, SoftDelete):
|
||||
|
||||
|
||||
class ClusterLock(BASE, SenlinBase):
|
||||
"""
|
||||
Store cluster locks for actions performed by multiple workers.
|
||||
"""Store cluster locks for actions performed by multiple workers.
|
||||
|
||||
Worker threads are able to grab this lock
|
||||
"""
|
||||
@@ -154,8 +153,7 @@ class ClusterLock(BASE, SenlinBase):
|
||||
|
||||
|
||||
class NodeLock(BASE, SenlinBase):
|
||||
"""
|
||||
Store node locks for actions performed by multiple workers.
|
||||
"""Store node locks for actions performed by multiple workers.
|
||||
|
||||
Worker threads are able to grab this lock
|
||||
"""
|
||||
|
||||
@@ -16,8 +16,7 @@ Base class for all drivers.
|
||||
|
||||
|
||||
class DriverBase(object):
|
||||
'''
|
||||
Base class for all drivers.
|
||||
'''
|
||||
'''Base class for all drivers.'''
|
||||
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
@@ -16,9 +16,8 @@ from senlin.openstack.orchestration.v1 import stack
|
||||
|
||||
|
||||
class HeatClient(base.DriverBase):
|
||||
'''
|
||||
Heat V1 driver.
|
||||
'''
|
||||
'''Heat V1 driver.'''
|
||||
|
||||
def __init__(self, context):
|
||||
conn = sdk.create_connection(context)
|
||||
self.session = conn.session
|
||||
|
||||
@@ -25,9 +25,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Action(object):
|
||||
'''
|
||||
An action can be performed on a cluster or a node of a cluster.
|
||||
'''
|
||||
'''An action can be performed on a cluster or a node of a cluster.'''
|
||||
|
||||
RETURNS = (
|
||||
RES_OK, RES_ERROR, RES_RETRY, RES_CANCEL, RES_TIMEOUT,
|
||||
) = (
|
||||
@@ -132,9 +131,8 @@ class Action(object):
|
||||
self.deleted_time = kwargs.get('deleted_time', None)
|
||||
|
||||
def store(self, context):
|
||||
'''
|
||||
Store the action record into database table.
|
||||
'''
|
||||
'''Store the action record into database table.'''
|
||||
|
||||
values = {
|
||||
'name': self.name,
|
||||
'context': self.context.to_dict(),
|
||||
@@ -169,8 +167,8 @@ class Action(object):
|
||||
|
||||
@classmethod
|
||||
def _from_db_record(cls, record):
|
||||
'''
|
||||
Construct a action object from database record.
|
||||
'''Construct a action object from database record.
|
||||
|
||||
:param context: the context used for DB operations;
|
||||
:param record: a DB action object that contains all fields.
|
||||
'''
|
||||
@@ -198,9 +196,8 @@ class Action(object):
|
||||
|
||||
@classmethod
|
||||
def load(cls, context, action_id):
|
||||
'''
|
||||
Retrieve an action from database.
|
||||
'''
|
||||
'''Retrieve an action from database.'''
|
||||
|
||||
action = db_api.action_get(context, action_id)
|
||||
if action is None:
|
||||
msg = _('No action with id "%s" exists') % action_id
|
||||
@@ -211,9 +208,8 @@ class Action(object):
|
||||
@classmethod
|
||||
def load_all(cls, context, filters=None, limit=None, marker=None,
|
||||
sort_keys=None, sort_dir=None, show_deleted=False):
|
||||
'''
|
||||
Retrieve all actions of from database.
|
||||
'''
|
||||
'''Retrieve all actions of from database.'''
|
||||
|
||||
records = db_api.action_get_all(context, filters=filters,
|
||||
limit=limit, marker=marker,
|
||||
sort_keys=sort_keys,
|
||||
@@ -228,8 +224,8 @@ class Action(object):
|
||||
db_api.action_delete(context, action_id, force)
|
||||
|
||||
def execute(self, **kwargs):
|
||||
'''
|
||||
Execute the action.
|
||||
'''Execute the action.
|
||||
|
||||
In theory, the action encapsulates all information needed for
|
||||
execution. 'kwargs' may specify additional parameters.
|
||||
:param kwargs: additional parameters that may override the default
|
||||
@@ -241,8 +237,8 @@ class Action(object):
|
||||
return NotImplemented
|
||||
|
||||
def set_status(self, status):
|
||||
'''
|
||||
Set action status.
|
||||
'''Set action status.
|
||||
|
||||
This is not merely about a db record update.
|
||||
'''
|
||||
if status == self.SUCCEEDED:
|
||||
@@ -260,8 +256,7 @@ class Action(object):
|
||||
return action.status
|
||||
|
||||
def policy_check(self, cluster_id, target):
|
||||
"""
|
||||
Check all policies attached to cluster and give result
|
||||
"""Check all policies attached to cluster and give result.
|
||||
|
||||
:param target: A tuple of ('when', action_name)
|
||||
"""
|
||||
|
||||
@@ -28,9 +28,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ClusterAction(base.Action):
|
||||
'''
|
||||
An action performed on a cluster.
|
||||
'''
|
||||
'''An action performed on a cluster.'''
|
||||
|
||||
ACTIONS = (
|
||||
CLUSTER_CREATE, CLUSTER_DELETE, CLUSTER_UPDATE,
|
||||
CLUSTER_ADD_NODES, CLUSTER_DEL_NODES,
|
||||
|
||||
@@ -20,9 +20,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NodeAction(base.Action):
|
||||
'''
|
||||
An action performed on a cluster member.
|
||||
'''
|
||||
'''An action performed on a cluster member.'''
|
||||
|
||||
ACTIONS = (
|
||||
NODE_CREATE, NODE_DELETE, NODE_UPDATE,
|
||||
NODE_JOIN_CLUSTER, NODE_LEAVE_CLUSTER,
|
||||
|
||||
@@ -21,8 +21,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PolicyAction(base.Action):
|
||||
'''
|
||||
An action performed on a cluster policy.
|
||||
'''An action performed on a cluster policy.
|
||||
|
||||
Note that these can be treated as cluster operations instead of operations
|
||||
on a policy itself.
|
||||
|
||||
@@ -21,8 +21,7 @@ from senlin.profiles import base as profiles
|
||||
|
||||
|
||||
class Cluster(periodic_task.PeriodicTasks):
|
||||
'''
|
||||
A cluster is a set of homogeneous objects of the same profile.
|
||||
'''A cluster is a set of homogeneous objects of the same profile.
|
||||
|
||||
All operations are performed without further checking because the
|
||||
checkings are supposed to be de done before/after/during an action is
|
||||
@@ -38,10 +37,11 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
)
|
||||
|
||||
def __init__(self, name, profile_id, size=0, **kwargs):
|
||||
'''
|
||||
Intialize a cluster object.
|
||||
'''Intialize a cluster object.
|
||||
|
||||
The cluster defaults to have 0 nodes with no profile assigned.
|
||||
'''
|
||||
|
||||
self.id = kwargs.get('id', None)
|
||||
self.name = name
|
||||
self.profile_id = profile_id
|
||||
@@ -74,8 +74,8 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
|
||||
@classmethod
|
||||
def _from_db_record(cls, record):
|
||||
'''
|
||||
Construct a cluster object from database record.
|
||||
'''Construct a cluster object from database record.
|
||||
|
||||
:param context: the context used for DB operations;
|
||||
:param record: a DB cluster object that will receive all fields;
|
||||
'''
|
||||
@@ -107,9 +107,8 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
|
||||
@classmethod
|
||||
def load(cls, context, cluster_id, show_deleted=False):
|
||||
'''
|
||||
Retrieve a cluster from database.
|
||||
'''
|
||||
'''Retrieve a cluster from database.'''
|
||||
|
||||
record = db_api.cluster_get(context, cluster_id,
|
||||
show_deleted=show_deleted)
|
||||
cluster = cls._from_db_record(record)
|
||||
@@ -120,9 +119,8 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
def load_all(cls, context, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, tenant_safe=True,
|
||||
show_deleted=False, show_nested=False):
|
||||
'''
|
||||
Retrieve all clusters from database.
|
||||
'''
|
||||
'''Retrieve all clusters from database.'''
|
||||
|
||||
records = db_api.cluster_get_all(context, limit, marker, sort_keys,
|
||||
sort_dir, filters, tenant_safe,
|
||||
show_deleted, show_nested)
|
||||
@@ -133,10 +131,11 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
yield cluster
|
||||
|
||||
def store(self, context):
|
||||
'''
|
||||
Store the cluster in database and return its ID.
|
||||
'''Store the cluster in database and return its ID.
|
||||
|
||||
If the ID already exists, we do an update.
|
||||
'''
|
||||
|
||||
values = {
|
||||
'name': self.name,
|
||||
'profile_id': self.profile_id,
|
||||
@@ -194,9 +193,8 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
return info
|
||||
|
||||
def set_status(self, context, status, reason=None):
|
||||
'''
|
||||
Set status of the cluster.
|
||||
'''
|
||||
'''Set status of the cluster.'''
|
||||
|
||||
values = {}
|
||||
now = datetime.datetime.utcnow()
|
||||
if status == self.ACTIVE:
|
||||
@@ -215,25 +213,25 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
# generate event record
|
||||
|
||||
def do_create(self, context, **kwargs):
|
||||
'''Invoked at the beginning of cluster creating progress to set
|
||||
cluster status to CREATING.
|
||||
'''
|
||||
Invoked at the beginning of cluster creating
|
||||
progress to set cluster status to CREATING.
|
||||
'''
|
||||
|
||||
self.set_status(context, self.CREATING)
|
||||
return True
|
||||
|
||||
def do_delete(self, context, **kwargs):
|
||||
'''
|
||||
Invoked at the end of entire cluster deleting
|
||||
'''Invoked at the end of entire cluster deleting
|
||||
progress to set cluster status to DELETED.
|
||||
'''
|
||||
|
||||
self.set_status(context, self.DELETED)
|
||||
|
||||
def do_update(self, context, new_profile_id, **kwargs):
|
||||
'''
|
||||
Invoked at the beginning of cluster updating progress
|
||||
'''Invoked at the beginning of cluster updating progress
|
||||
to check profile and set cluster status to UPDATING.
|
||||
'''
|
||||
|
||||
self.set_status(self.UPDATING)
|
||||
# Profile type checking is done here because the do_update logic can
|
||||
# be triggered from API or Webhook
|
||||
@@ -273,9 +271,8 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
pass
|
||||
|
||||
def del_nodes(self, node_ids):
|
||||
'''
|
||||
Remove nodes from current cluster.
|
||||
'''
|
||||
'''Remove nodes from current cluster.'''
|
||||
|
||||
deleted = []
|
||||
for node_id in node_ids:
|
||||
node = db_api.node_get(node_id)
|
||||
@@ -284,9 +281,8 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
return deleted
|
||||
|
||||
def attach_policy(self, policy_id):
|
||||
'''
|
||||
Attach specified policy instance to this cluster.
|
||||
'''
|
||||
'''Attach specified policy instance to this cluster.'''
|
||||
|
||||
# TODO(Qiming): check conflicts with existing policies
|
||||
self.policies.append(policy_id)
|
||||
|
||||
@@ -327,5 +323,6 @@ class Cluster(periodic_task.PeriodicTasks):
|
||||
pass
|
||||
|
||||
def periodic_tasks(self, context, raise_on_error=False):
|
||||
"""Tasks to be run at a periodic interval."""
|
||||
'''Tasks to be run at a periodic interval.'''
|
||||
|
||||
return self.run_periodic_tasks(context, raise_on_error=raise_on_error)
|
||||
|
||||
@@ -26,9 +26,9 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
@profiler.trace_cls("rpc")
|
||||
class Dispatcher(service.Service):
|
||||
'''
|
||||
Listen on an AMQP queue named for the engine. Receive
|
||||
notification from engine services and schedule actions.
|
||||
'''Listen on an AMQP queue named for the engine.
|
||||
|
||||
Receive notification from engine services and schedule actions.
|
||||
'''
|
||||
|
||||
OPERATIONS = (
|
||||
@@ -53,8 +53,7 @@ class Dispatcher(service.Service):
|
||||
server.start()
|
||||
|
||||
def listening(self, context):
|
||||
'''
|
||||
Respond affirmatively to confirm that the engine performing the
|
||||
'''Respond affirmatively to confirm that the engine performing the
|
||||
action is still alive.
|
||||
'''
|
||||
return True
|
||||
@@ -86,13 +85,13 @@ class Dispatcher(service.Service):
|
||||
|
||||
|
||||
def notify(context, call, engine_id, *args, **kwargs):
|
||||
"""
|
||||
Send notification to dispatcher
|
||||
'''Send notification to dispatcher
|
||||
|
||||
:param context: rpc request context
|
||||
:param call: remote method want to call
|
||||
:param engine_id: dispatcher want to notify, if None, broadcast
|
||||
"""
|
||||
'''
|
||||
|
||||
timeout = cfg.CONF.engine_life_check_timeout
|
||||
client = rpc_messaging.get_rpc_client(version=attr.RPC_API_VERSION)
|
||||
|
||||
|
||||
@@ -38,9 +38,8 @@ def global_env():
|
||||
|
||||
|
||||
class Environment(object):
|
||||
'''
|
||||
An object that contains all profiles, policies and customizations.
|
||||
'''
|
||||
'''An object that contains all profiles, policies and customizations.'''
|
||||
|
||||
SECTIONS = (
|
||||
PARAMETERS, CUSTOM_PROFILES, CUSTOM_POLICIES,
|
||||
) = (
|
||||
@@ -48,8 +47,7 @@ class Environment(object):
|
||||
)
|
||||
|
||||
def __init__(self, env=None, is_global=False):
|
||||
'''
|
||||
Create an Environment from a dict.
|
||||
'''Create an Environment from a dict.
|
||||
|
||||
:param env: the json environment
|
||||
:param is_global: boolean indicating if this is a user created one.
|
||||
@@ -75,9 +73,8 @@ class Environment(object):
|
||||
self.policy_registry.load(custom_policies)
|
||||
|
||||
def parse(self, env_str):
|
||||
'''
|
||||
Parse a string format environment file into a dictionary.
|
||||
'''
|
||||
'''Parse a string format environment file into a dictionary.'''
|
||||
|
||||
if env_str is None:
|
||||
return {}
|
||||
|
||||
@@ -97,9 +94,8 @@ class Environment(object):
|
||||
return env
|
||||
|
||||
def load(self, env_dict):
|
||||
'''
|
||||
Load environment from the given dictionary.
|
||||
'''
|
||||
'''Load environment from the given dictionary.'''
|
||||
|
||||
self.params.update(env_dict.get(self.PARAMETERS, {}))
|
||||
self.profile_registry.load(env_dict.get(self.CUSTOM_PROFILES, {}))
|
||||
self.policy_registry.load(env_dict.get(self.CUSTOM_POLICIES, {}))
|
||||
@@ -151,9 +147,8 @@ class Environment(object):
|
||||
return self.policy_registry.get_types()
|
||||
|
||||
def read_global_environment(self):
|
||||
'''
|
||||
Read and parse global enviroment files.
|
||||
'''
|
||||
'''Read and parse global enviroment files.'''
|
||||
|
||||
cfg.CONF.import_opt('environment_dir', 'senlin.common.config')
|
||||
env_dir = cfg.CONF.environment_dir
|
||||
|
||||
|
||||
@@ -33,9 +33,8 @@ class_mapping = {
|
||||
|
||||
|
||||
class Event(object):
|
||||
'''
|
||||
Class capturing a cluster operation or state change.
|
||||
'''
|
||||
'''Class capturing a cluster operation or state change.'''
|
||||
|
||||
def __init__(self, level, context, entity, action, status,
|
||||
timestamp=None, reason='', entity_type='CLUSTER'):
|
||||
self.level = level
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
import datetime
|
||||
|
||||
from senlin.common import exception
|
||||
from senlin.common.i18n import _
|
||||
from senlin.common.i18n import _LE
|
||||
from senlin.common.i18n import _LW
|
||||
from senlin.db import api as db_api
|
||||
@@ -24,8 +25,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Node(object):
|
||||
'''
|
||||
A node is an object that can belong to at most one single cluster.
|
||||
'''A node is an object that can belong to at most one single cluster.
|
||||
|
||||
All operations are performed without further checking because the
|
||||
checkings are supposed to be de done before/after/during an action is
|
||||
@@ -70,8 +70,7 @@ class Node(object):
|
||||
}
|
||||
|
||||
def store(self, context):
|
||||
'''
|
||||
Store the node record into database table.
|
||||
'''Store the node record into database table.
|
||||
|
||||
The invocation of DB API could be a node_create or a node_update,
|
||||
depending on whether node has an ID assigned.
|
||||
@@ -108,8 +107,8 @@ class Node(object):
|
||||
|
||||
@classmethod
|
||||
def from_db_record(cls, context, record):
|
||||
'''
|
||||
Construct a node object from database record.
|
||||
'''Construct a node object from database record.
|
||||
|
||||
:param context: the context used for DB operations;
|
||||
:param record: a DB node object that contains all fields;
|
||||
'''
|
||||
@@ -132,9 +131,8 @@ class Node(object):
|
||||
|
||||
@classmethod
|
||||
def load(cls, context, node_id):
|
||||
'''
|
||||
Retrieve a node from database.
|
||||
'''
|
||||
'''Retrieve a node from database.'''
|
||||
|
||||
record = db_api.node_get(context, node_id)
|
||||
|
||||
if record is None:
|
||||
@@ -147,9 +145,8 @@ class Node(object):
|
||||
def load_all(cls, context, cluster_id=None, show_deleted=False,
|
||||
limit=None, marker=None, sort_keys=None, sort_dir=None,
|
||||
filters=None, tenant_safe=True):
|
||||
'''
|
||||
Retrieve all nodes of from database.
|
||||
'''
|
||||
'''Retrieve all nodes of from database.'''
|
||||
|
||||
records = db_api.node_get_all(context, cluster_id=cluster_id,
|
||||
show_deleted=show_deleted,
|
||||
limit=limit, marker=marker,
|
||||
|
||||
@@ -17,10 +17,10 @@ import six
|
||||
from six.moves import urllib
|
||||
import yaml
|
||||
|
||||
from senlin.common import i18n
|
||||
from senlin.common.i18n import _
|
||||
from senlin.common.i18n import _LE
|
||||
from senlin.openstack.common import log as logging
|
||||
|
||||
_LE = i18n._LE
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
# Try LibYAML if available
|
||||
@@ -102,9 +102,8 @@ def simple_parse(in_str):
|
||||
|
||||
|
||||
def parse_profile(profile_str):
|
||||
'''
|
||||
Parse and validate the specified string as a profile.
|
||||
'''
|
||||
'''Parse and validate the specified string as a profile.'''
|
||||
|
||||
data = simple_parse(profile_str)
|
||||
|
||||
# TODO(Qiming):
|
||||
@@ -114,9 +113,8 @@ def parse_profile(profile_str):
|
||||
|
||||
|
||||
def parse_policy(policy_str):
|
||||
'''
|
||||
Parse and validate the specified string as a policy.
|
||||
'''
|
||||
'''Parse and validate the specified string as a policy.'''
|
||||
|
||||
data = simple_parse(policy_str)
|
||||
|
||||
# TODO(Qiming):
|
||||
@@ -126,9 +124,8 @@ def parse_policy(policy_str):
|
||||
|
||||
|
||||
def parse_action(action):
|
||||
'''
|
||||
Parse and validate the specified string as a action.
|
||||
'''
|
||||
'''Parse and validate the specified string as a action.'''
|
||||
|
||||
if not isinstance(action, six.string_types):
|
||||
# TODO(Qiming): Throw exception
|
||||
return None
|
||||
|
||||
@@ -21,12 +21,11 @@ LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class PluginInfo(object):
|
||||
'''
|
||||
Base mapping of plugin type to implementation.
|
||||
'''
|
||||
'''Base mapping of plugin type to implementation.'''
|
||||
|
||||
def __new__(cls, registry, name, plugin, **kwargs):
|
||||
'''
|
||||
Create a new PluginInfo of the appropriate class.
|
||||
'''Create a new PluginInfo of the appropriate class.
|
||||
|
||||
Placeholder for class hierarchy extensibility
|
||||
'''
|
||||
return super(PluginInfo, cls).__new__(cls)
|
||||
@@ -65,9 +64,7 @@ class PluginInfo(object):
|
||||
|
||||
|
||||
class Registry(object):
|
||||
'''
|
||||
A registry for managing profile or policy classes.
|
||||
'''
|
||||
'''A registry for managing profile or policy classes.'''
|
||||
|
||||
def __init__(self, registry_name, global_registry=None):
|
||||
self.registry_name = registry_name
|
||||
@@ -76,8 +73,7 @@ class Registry(object):
|
||||
self.global_registry = global_registry
|
||||
|
||||
def _register_info(self, name, info):
|
||||
'''
|
||||
place the new info in the correct location in the registry.
|
||||
'''place the new info in the correct location in the registry.
|
||||
|
||||
:param path: a list of keys ['profiles', 'my_stack', 'os.heat.stack'],
|
||||
or ['policies', 'my_policy', 'ScalingPolicy']
|
||||
@@ -140,7 +136,7 @@ class Registry(object):
|
||||
return info.plugin if info else None
|
||||
|
||||
def as_dict(self):
|
||||
"""Return profiles in a dict format."""
|
||||
'''Return profiles in a dict format.'''
|
||||
def _as_dict(level):
|
||||
tmp = {}
|
||||
for k, v in iter(level.items()):
|
||||
|
||||
@@ -34,8 +34,8 @@ ACTION_CONTROL_REQUEST = (
|
||||
|
||||
|
||||
class ThreadGroupManager(object):
|
||||
"""
|
||||
"""
|
||||
'''Thread group manager.'''
|
||||
|
||||
def __init__(self):
|
||||
super(ThreadGroupManager, self).__init__()
|
||||
self.threads = {}
|
||||
@@ -46,10 +46,10 @@ class ThreadGroupManager(object):
|
||||
self.add_timer(cfg.CONF.periodic_interval, self._service_task)
|
||||
|
||||
def _service_task(self):
|
||||
'''
|
||||
This is a dummy task which gets queued on the service.Service
|
||||
threadgroup. Without this service.Service sees nothing running
|
||||
i.e has nothing to wait() on, so the process exits..
|
||||
'''Dummy task which gets queued on the service.Service threadgroup.
|
||||
|
||||
Without this service.Service sees nothing running i.e has nothing to
|
||||
wait() on, so the process exits..
|
||||
This could also be used to trigger periodic non-cluster-specific
|
||||
housekeeping tasks
|
||||
|
||||
@@ -59,24 +59,20 @@ class ThreadGroupManager(object):
|
||||
pass
|
||||
|
||||
def start(self, func, *args, **kwargs):
|
||||
"""
|
||||
Run the given method in a sub-thread.
|
||||
"""
|
||||
'''Run the given method in a sub-thread.'''
|
||||
|
||||
return self.group.add_thread(func, *args, **kwargs)
|
||||
|
||||
def start_action_thread(self, context, action, *args, **kwargs):
|
||||
"""
|
||||
Run the given action in a sub-thread and release the action lock
|
||||
'''Run the given action in a sub-thread and release the action lock
|
||||
when the thread finishes.
|
||||
|
||||
:param context: The context of rpc request
|
||||
:param action: The action to run in thread
|
||||
'''
|
||||
|
||||
"""
|
||||
def release(gt, context, action):
|
||||
"""
|
||||
Callback function that will be passed to GreenThread.link().
|
||||
"""
|
||||
'''Callback function that will be passed to GreenThread.link().'''
|
||||
# Remove action thread from thread list
|
||||
self.threads.pop(action.id)
|
||||
|
||||
@@ -86,10 +82,11 @@ class ThreadGroupManager(object):
|
||||
return th
|
||||
|
||||
def add_timer(self, interval, func, *args, **kwargs):
|
||||
"""
|
||||
Define a periodic task, to be run in a separate thread, in the target
|
||||
threadgroups. Periodicity is cfg.CONF.periodic_interval
|
||||
"""
|
||||
'''Define a periodic task, to be run in a separate thread, in the
|
||||
target threadgroups.
|
||||
Interval is from cfg.CONF.periodic_interval
|
||||
'''
|
||||
|
||||
self.group.add_timer(cfg.CONF.periodic_interval, func, *args, **kwargs)
|
||||
|
||||
def stop_timers(self):
|
||||
@@ -116,13 +113,12 @@ class ThreadGroupManager(object):
|
||||
|
||||
|
||||
def ActionProc(context, action, wait_time=1, **kwargs):
|
||||
"""
|
||||
Start and run action progress.
|
||||
'''Start and run action progress.
|
||||
|
||||
Action progress will sleep for `wait_time` seconds between
|
||||
each step. To avoid sleeping, pass `None` for `wait_time`.
|
||||
"""
|
||||
# Do the first step
|
||||
'''
|
||||
|
||||
LOG.debug('Starting %s' % six.text_type(action.action))
|
||||
|
||||
result = action.execute()
|
||||
@@ -145,14 +141,14 @@ def ActionProc(context, action, wait_time=1, **kwargs):
|
||||
|
||||
|
||||
def start_action(context, action_id, engine_id, tgm):
|
||||
"""
|
||||
Start an action execution progress using given ThreadGroupManager
|
||||
'''Start an action execution progress using given ThreadGroupManager.
|
||||
|
||||
:param context: The context of rpc request
|
||||
:param action_id: The id of action to run in thread
|
||||
:param engine_id: The id of engine try to lock the action
|
||||
:param tgm: The ThreadGroupManager of the engine
|
||||
"""
|
||||
'''
|
||||
|
||||
action = base_action.Action.load(context, action_id)
|
||||
|
||||
action.start_time = wallclock()
|
||||
@@ -173,46 +169,41 @@ def start_action(context, action_id, engine_id, tgm):
|
||||
|
||||
|
||||
def suspend_action(context, action_id):
|
||||
"""
|
||||
Try to suspend an action execution progress
|
||||
'''Suspend an action execution progress.
|
||||
|
||||
:param context: The context of rpc request
|
||||
:param action_id: The id of action to run in thread
|
||||
"""
|
||||
'''
|
||||
# Set action control flag to suspend
|
||||
# TODO(anyone): need db_api support
|
||||
db_api.action_control(context, action_id, ACTION_SUSPEND)
|
||||
|
||||
|
||||
def resume_action(context, action_id):
|
||||
"""
|
||||
Try to resume an action execution progress
|
||||
'''Resume an action execution progress.
|
||||
|
||||
:param context: The context of rpc request
|
||||
:param action_id: The id of action to run in thread
|
||||
"""
|
||||
'''
|
||||
# Set action control flag to suspend
|
||||
# TODO(anyone): need db_api support
|
||||
db_api.action_control(context, action_id, ACTION_RESUME)
|
||||
|
||||
|
||||
def cancel_action(context, action_id):
|
||||
"""
|
||||
Try to cancel an action execution progress
|
||||
'''Try to cancel an action execution progress.
|
||||
|
||||
:param context: The context of rpc request
|
||||
:param action_id: The id of action to run in thread
|
||||
"""
|
||||
'''
|
||||
# Set action control flag to cancel
|
||||
# TODO(anyone): need db_api support
|
||||
db_api.action_control(context, action_id, ACTION_CANCEL)
|
||||
|
||||
|
||||
def action_control_flag(action):
|
||||
"""
|
||||
Check whether there are some action control requests
|
||||
need to be handled.
|
||||
"""
|
||||
'''Check whether there are some action control requests.'''
|
||||
|
||||
# Check timeout first, if true, return timeout message
|
||||
if action.timeout is not None and action_timeout(action):
|
||||
LOG.debug('Action %s run timeout' % action.id)
|
||||
@@ -225,9 +216,8 @@ def action_control_flag(action):
|
||||
|
||||
|
||||
def action_cancelled(action):
|
||||
"""
|
||||
Check whether an action's control flag is set to cancel
|
||||
"""
|
||||
'''Check whether an action is flagged to be cancelled.'''
|
||||
|
||||
if action_control_flag(action) == ACTION_CANCEL:
|
||||
return True
|
||||
else:
|
||||
@@ -235,9 +225,8 @@ def action_cancelled(action):
|
||||
|
||||
|
||||
def action_suspended(action):
|
||||
"""
|
||||
Check whether an action's control flag is set to suspend
|
||||
"""
|
||||
'''Check whether an action's control flag is set to suspend.'''
|
||||
|
||||
if action_control_flag(action) == ACTION_SUSPEND:
|
||||
return True
|
||||
else:
|
||||
@@ -245,9 +234,8 @@ def action_suspended(action):
|
||||
|
||||
|
||||
def action_resumed(action):
|
||||
"""
|
||||
Check whether an action's control flag is set to suspend
|
||||
"""
|
||||
'''Check whether an action's control flag is set to resume.'''
|
||||
|
||||
if action_control_flag(action) == ACTION_RESUME:
|
||||
return True
|
||||
else:
|
||||
@@ -255,9 +243,8 @@ def action_resumed(action):
|
||||
|
||||
|
||||
def action_timeout(action):
|
||||
"""
|
||||
Return True if an action has run timeout, False otherwise.
|
||||
"""
|
||||
'''Return True if an action has run timeout, False otherwise.'''
|
||||
|
||||
time_lapse = wallclock() - action.start_time
|
||||
|
||||
if time_lapse > action.timeout:
|
||||
@@ -267,11 +254,11 @@ def action_timeout(action):
|
||||
|
||||
|
||||
def reschedule(action, sleep_time=1):
|
||||
"""
|
||||
Eventlet Sleep for the specified number of seconds.
|
||||
'''Eventlet Sleep for the specified number of seconds.
|
||||
|
||||
:param sleep_time: seconds to sleep; if None, no sleep;
|
||||
"""
|
||||
'''
|
||||
|
||||
if sleep_time is not None:
|
||||
LOG.debug('Action %s sleep for %s seconds' % (
|
||||
action.id, sleep_time))
|
||||
@@ -279,16 +266,14 @@ def reschedule(action, sleep_time=1):
|
||||
|
||||
|
||||
def action_wait(action):
|
||||
"""
|
||||
Keep waiting util action resume control flag is set
|
||||
"""
|
||||
'''Keep waiting util action resume control flag is set.'''
|
||||
|
||||
while not action_resumed(action):
|
||||
reschedule(action, sleep_time=1)
|
||||
continue
|
||||
|
||||
|
||||
def sleep(sleep_time):
|
||||
'''
|
||||
Interface for sleeping.
|
||||
'''
|
||||
'''Interface for sleeping.'''
|
||||
|
||||
eventlet.sleep(sleep_time)
|
||||
|
||||
@@ -31,6 +31,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BaseLock(object):
|
||||
'''Base class for locks.'''
|
||||
|
||||
def __init__(self, context, target, engine_id):
|
||||
self.context = context
|
||||
self.target = target
|
||||
@@ -53,19 +55,19 @@ class BaseLock(object):
|
||||
return str(uuid.uuid4())
|
||||
|
||||
def try_acquire(self):
|
||||
"""
|
||||
Try to acquire a lock for target, but don't raise an ActionInProgress
|
||||
exception or try to steal lock.
|
||||
"""
|
||||
'''Try to acquire a lock for target.
|
||||
|
||||
It won't raise an ActionInProgress exception or try to steal lock.
|
||||
'''
|
||||
return self.lock_create(self.target.id, self.engine_id)
|
||||
|
||||
def acquire(self, retry=True):
|
||||
"""
|
||||
Acquire a lock on the target.
|
||||
'''Acquire a lock on the target.
|
||||
|
||||
:param retry: When True, retry if lock was released while stealing.
|
||||
:type retry: boolean
|
||||
"""
|
||||
'''
|
||||
|
||||
lock_engine_id = self.lock_create(self.target.id, self.engine_id)
|
||||
if lock_engine_id is None:
|
||||
LOG.debug("Engine %(engine)s acquired lock on %(target_type)s "
|
||||
@@ -135,11 +137,11 @@ class BaseLock(object):
|
||||
|
||||
@contextlib.contextmanager
|
||||
def thread_lock(self, target_id):
|
||||
"""
|
||||
Acquire a lock and release it only if there is an exception. The
|
||||
release method still needs to be scheduled to be run at the
|
||||
'''Acquire a lock and release it only if there is an exception.
|
||||
|
||||
The release method still needs to be scheduled to be run at the
|
||||
end of the thread using the Thread.link method.
|
||||
"""
|
||||
'''
|
||||
try:
|
||||
self.acquire()
|
||||
yield
|
||||
@@ -149,11 +151,13 @@ class BaseLock(object):
|
||||
|
||||
@contextlib.contextmanager
|
||||
def try_thread_lock(self, target_id):
|
||||
"""
|
||||
'''Acquire the lock using try_acquire.
|
||||
|
||||
Similar to thread_lock, but acquire the lock using try_acquire
|
||||
and only release it upon any exception after a successful
|
||||
acquisition.
|
||||
"""
|
||||
'''
|
||||
|
||||
result = None
|
||||
try:
|
||||
result = self.try_acquire()
|
||||
|
||||
@@ -70,15 +70,15 @@ def request_context(func):
|
||||
|
||||
@profiler.trace_cls("rpc")
|
||||
class EngineService(service.Service):
|
||||
"""
|
||||
Manages the running instances from creation to destruction.
|
||||
'''Manages the running instances from creation to destruction.
|
||||
|
||||
All the methods in here are called from the RPC backend. This is
|
||||
all done dynamically so if a call is made via RPC that does not
|
||||
have a corresponding method here, an exception will be thrown when
|
||||
it attempts to call into this class. Arguments to these methods
|
||||
are also dynamically added and will be named as keyword arguments
|
||||
by the RPC caller.
|
||||
"""
|
||||
'''
|
||||
|
||||
def __init__(self, host, topic, manager=None,
|
||||
periodic_enable=None, periodic_fuzzy_delay=None,
|
||||
@@ -244,9 +244,8 @@ class EngineService(service.Service):
|
||||
|
||||
@request_context
|
||||
def cluster_find(self, context, identity):
|
||||
'''
|
||||
Find a cluster with the given identity (could be name or ID).
|
||||
'''
|
||||
'''Find a cluster with the given identity (could be name or ID).'''
|
||||
|
||||
if uuidutils.is_uuid_like(identity):
|
||||
db_cluster = db_api.cluster_get(context, identity,
|
||||
show_deleted=True)
|
||||
|
||||
@@ -57,7 +57,8 @@ _levelNames = {
|
||||
|
||||
|
||||
def getLevelName(level):
|
||||
'''
|
||||
'''Get a level name or number.
|
||||
|
||||
Return a level name if given a numeric value; or return a value if given
|
||||
a string. If level is not predefined, "Level %s" will be returned.
|
||||
'''
|
||||
|
||||
@@ -11,14 +11,14 @@
|
||||
# under the License.
|
||||
|
||||
from senlin.common import exception
|
||||
from senlin.common.i18n import _
|
||||
from senlin.db import api as db_api
|
||||
from senlin.engine import environment
|
||||
|
||||
|
||||
class Policy(object):
|
||||
'''
|
||||
Base class for policies.
|
||||
'''
|
||||
'''Base class for policies.'''
|
||||
|
||||
ENFORCEMENT_LEVELS = (
|
||||
CRITICAL, ERROR, WARNING, INFO, DEBUG,
|
||||
) = (
|
||||
@@ -32,9 +32,8 @@ class Policy(object):
|
||||
)
|
||||
|
||||
def __new__(cls, type_name, name, **kwargs):
|
||||
'''
|
||||
Create a new policy of the appropriate class.
|
||||
'''
|
||||
'''Create a new policy of the appropriate class.'''
|
||||
|
||||
if cls != Policy:
|
||||
PolicyClass = cls
|
||||
else:
|
||||
@@ -54,8 +53,8 @@ class Policy(object):
|
||||
self.data = kwargs.get('data', {})
|
||||
|
||||
def store(self):
|
||||
'''
|
||||
Store the policy object into database table.
|
||||
'''Store the policy object into database table.
|
||||
|
||||
This could be a policy_create or a policy_update DB API invocation,
|
||||
depends on whether self.id is set.
|
||||
'''
|
||||
@@ -77,11 +76,8 @@ class Policy(object):
|
||||
|
||||
@classmethod
|
||||
def from_db_record(cls, context, record):
|
||||
'''
|
||||
Construct a policy object from a database record.
|
||||
:param context:
|
||||
:param record:
|
||||
'''
|
||||
'''Construct a policy object from a database record.'''
|
||||
|
||||
kwargs = {
|
||||
'id': record.id,
|
||||
'name': record.name,
|
||||
@@ -96,9 +92,8 @@ class Policy(object):
|
||||
|
||||
@classmethod
|
||||
def load(cls, context, policy_id):
|
||||
'''
|
||||
Retrieve and reconstruct a policy object from DB.
|
||||
'''
|
||||
'''Retrieve and reconstruct a policy object from DB.'''
|
||||
|
||||
policy = db_api.policy_get(context, policy_id)
|
||||
if policy is None:
|
||||
msg = _('No policy with id "%s" exists') % policy_id
|
||||
@@ -107,23 +102,20 @@ class Policy(object):
|
||||
return cls.from_db_record(context, policy)
|
||||
|
||||
def pre_op(self, cluster_id, action, **kwargs):
|
||||
'''
|
||||
Force all subclasses to implement an operation that will be invoked
|
||||
'''Force all subclasses to implement an operation that will be invoked
|
||||
before an action.
|
||||
'''
|
||||
return NotImplemented
|
||||
|
||||
def enforce(self, cluster_id, action, **kwargs):
|
||||
'''
|
||||
Force all subclasses to implement an operation that can be called
|
||||
'''Force all subclasses to implement an operation that can be called
|
||||
during an action.
|
||||
'''
|
||||
return NotImplemented
|
||||
|
||||
def post_op(self, cluster_id, action, **kwargs):
|
||||
'''
|
||||
Force all subclasses to implement an operation that will be performed
|
||||
after an action.
|
||||
'''Force all subclasses to implement an operation that will be
|
||||
performed after an action.
|
||||
'''
|
||||
return NotImplemented
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ from senlin.policies import base
|
||||
|
||||
|
||||
class DeletionPolicy(base.Policy):
|
||||
'''
|
||||
Policy for deleting member(s) from a cluster.
|
||||
'''
|
||||
'''Policy for deleting member(s) from a cluster.'''
|
||||
|
||||
__type_name__ = 'DeletionPolicy'
|
||||
|
||||
@@ -51,8 +49,7 @@ class DeletionPolicy(base.Policy):
|
||||
random.seed()
|
||||
|
||||
def pre_op(self, cluster_id, action, **kwargs):
|
||||
'''
|
||||
The pre-op of a deletion policy returns the chosen victims
|
||||
'''The pre-op of a deletion policy returns the chosen victims
|
||||
that will be deleted.
|
||||
'''
|
||||
data = kwargs.get('data')
|
||||
|
||||
@@ -15,9 +15,7 @@ from senlin.policies import base
|
||||
|
||||
|
||||
class HealthPolicy(base.Policy):
|
||||
'''
|
||||
Policy for health checking for members of a cluster.
|
||||
'''
|
||||
'''Policy for health checking for members of a cluster.'''
|
||||
|
||||
__type_name__ = 'HealthPolicy'
|
||||
|
||||
|
||||
@@ -15,8 +15,7 @@ from senlin.policies import base
|
||||
|
||||
|
||||
class LoadBalancingPolicy(base.Policy):
|
||||
'''
|
||||
Policy for load balancing among members of a cluster.
|
||||
'''Policy for load balancing among members of a cluster.
|
||||
|
||||
This policy is expected to be enforced after the member list of a cluster
|
||||
is changed. We need to reload the load-balancer specified (or internally
|
||||
|
||||
@@ -15,8 +15,7 @@ from senlin.policies import base
|
||||
|
||||
|
||||
class PlacementPolicy(base.Policy):
|
||||
'''
|
||||
Policy for placing members of a cluster.
|
||||
'''Policy for placing members of a cluster.
|
||||
|
||||
This policy is expected to be enforced before new member(s) added to an
|
||||
existing cluster.
|
||||
|
||||
@@ -16,8 +16,7 @@ from senlin.policies import base
|
||||
|
||||
|
||||
class ScalingPolicy(base.Policy):
|
||||
'''
|
||||
Policy for chaning the size of a cluster.
|
||||
'''Policy for chaning the size of a cluster.
|
||||
|
||||
This policy is expected to be enforced before the member list of a cluster
|
||||
is changed.
|
||||
|
||||
@@ -15,8 +15,7 @@ from senlin.policies import base
|
||||
|
||||
|
||||
class UpdatePolicy(base.Policy):
|
||||
'''
|
||||
Policy for updating a cluster's node profile.
|
||||
'''Policy for updating a cluster's node profile.
|
||||
|
||||
Note that we differentiate the updates to the size(scale) of a cluster from
|
||||
the updates to the node profile. The former is handled by CreatePolicy,
|
||||
|
||||
@@ -17,8 +17,7 @@ __type_name__ = 'aws.autoscaling.launchconfig'
|
||||
|
||||
|
||||
class LaunchConfigProfile(base.Profile):
|
||||
'''
|
||||
Profile for an AWS AutoScaling LaunchConfiguration.
|
||||
'''Profile for an AWS AutoScaling LaunchConfiguration.
|
||||
|
||||
When this profile is used, the whole cluster is a Heat stack where each
|
||||
member is a YAML snippet that describes a
|
||||
@@ -44,9 +43,7 @@ class LaunchConfigProfile(base.Profile):
|
||||
self.PlaementTenancy = kwargs.get('PlacementTenancy')
|
||||
|
||||
def do_create(self):
|
||||
'''
|
||||
This method creates a YAML format Heat resource definition.
|
||||
'''
|
||||
'''This method creates a YAML format Heat resource definition.'''
|
||||
return {}
|
||||
|
||||
def do_delete(self):
|
||||
|
||||
@@ -31,13 +31,11 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Profile(object):
|
||||
'''
|
||||
Base class for profiles.
|
||||
'''
|
||||
'''Base class for profiles.'''
|
||||
|
||||
def __new__(cls, type_name, name, **kwargs):
|
||||
'''
|
||||
Create a new profile of the appropriate class.
|
||||
'''
|
||||
'''Create a new profile of the appropriate class.'''
|
||||
|
||||
if cls != Profile:
|
||||
ProfileClass = cls
|
||||
else:
|
||||
@@ -46,9 +44,8 @@ class Profile(object):
|
||||
return super(Profile, cls).__new__(ProfileClass)
|
||||
|
||||
def __init__(self, type_name, name, **kwargs):
|
||||
'''
|
||||
Initialize the profile with given parameters and a JSON object.
|
||||
'''
|
||||
'''Initialize the profile with given parameters and a JSON object.'''
|
||||
|
||||
self.name = name
|
||||
self.type = type_name
|
||||
self.id = kwargs.get('id', None)
|
||||
@@ -63,8 +60,8 @@ class Profile(object):
|
||||
|
||||
@classmethod
|
||||
def from_db_record(cls, context, record):
|
||||
'''
|
||||
Construct a profile object from database record.
|
||||
'''Construct a profile object from database record.
|
||||
|
||||
:param context: the context used for DB operations.
|
||||
:param record: a DB Profle object that contains all required fields.
|
||||
'''
|
||||
@@ -83,18 +80,16 @@ class Profile(object):
|
||||
|
||||
@classmethod
|
||||
def load(cls, context, profile_id):
|
||||
'''
|
||||
Retrieve a profile object from database.
|
||||
'''
|
||||
'''Retrieve a profile object from database.'''
|
||||
|
||||
record = db_api.profile_get(context, profile_id)
|
||||
return cls.from_db_record(context, record)
|
||||
|
||||
@classmethod
|
||||
def load_all(cls, context, limit=None, sort_keys=None, marker=None,
|
||||
sort_dir=None, filters=None, show_deleted=False):
|
||||
'''
|
||||
Retrieve all profiles from database.
|
||||
'''
|
||||
'''Retrieve all profiles from database.'''
|
||||
|
||||
records = db_api.profile_get_all(context, limit=limit, marker=marker,
|
||||
sort_keys=sort_keys,
|
||||
sort_dir=sort_dir,
|
||||
@@ -109,9 +104,8 @@ class Profile(object):
|
||||
db_api.profile_delete(context, profile_id)
|
||||
|
||||
def store(self, context):
|
||||
'''
|
||||
Store the profile into database and return its ID.
|
||||
'''
|
||||
'''Store the profile into database and return its ID.'''
|
||||
|
||||
values = {
|
||||
'name': self.name,
|
||||
'type': self.type,
|
||||
@@ -141,27 +135,22 @@ class Profile(object):
|
||||
return profile.do_update(obj, new_profile)
|
||||
|
||||
def do_create(self, obj):
|
||||
'''
|
||||
For subclass to override.
|
||||
'''
|
||||
'''For subclass to override.'''
|
||||
|
||||
return NotImplemented
|
||||
|
||||
def do_delete(self, obj):
|
||||
'''
|
||||
For subclass to override.
|
||||
'''
|
||||
'''For subclass to override.'''
|
||||
|
||||
return NotImplemented
|
||||
|
||||
def do_update(self, obj, new_profile):
|
||||
'''
|
||||
For subclass to override.
|
||||
'''
|
||||
'''For subclass to override.'''
|
||||
|
||||
return NotImplemented
|
||||
|
||||
def do_check(self, obj):
|
||||
'''
|
||||
For subclass to override.
|
||||
'''
|
||||
'''For subclass to override.'''
|
||||
return NotImplemented
|
||||
|
||||
def healty_check(self, context):
|
||||
|
||||
@@ -17,8 +17,8 @@ __type_name__ = 'os.heat.resource'
|
||||
|
||||
|
||||
class ResourceProfile(base.Profile):
|
||||
'''
|
||||
Profile for an OpenStack Heat resource.
|
||||
'''Profile for an OpenStack Heat resource.
|
||||
|
||||
When this profile is used, the whole cluster is Heat stack, composed
|
||||
of resources initialzed from this profile.
|
||||
'''
|
||||
@@ -26,10 +26,6 @@ class ResourceProfile(base.Profile):
|
||||
super(ResourceProfile, self).__init__(name, type_name, kwargs)
|
||||
|
||||
def do_create(self):
|
||||
'''
|
||||
A resource is represented as a YAML snippet that can be composed
|
||||
into a Heat stack.
|
||||
'''
|
||||
return {}
|
||||
|
||||
def do_delete(self, id):
|
||||
|
||||
@@ -14,6 +14,7 @@ import six
|
||||
|
||||
from senlin.common import context
|
||||
from senlin.common import exception
|
||||
from senlin.common.i18n import _
|
||||
from senlin.drivers import heat_v1 as heatclient
|
||||
from senlin.engine import scheduler
|
||||
from senlin.openstack.common import log as logging
|
||||
@@ -23,8 +24,8 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StackProfile(base.Profile):
|
||||
'''
|
||||
Profile for an OpenStack Heat stack.
|
||||
'''Profile for an OpenStack Heat stack.
|
||||
|
||||
When this profile is used, the whole cluster is a collection of Heat
|
||||
stacks.
|
||||
'''
|
||||
@@ -54,9 +55,8 @@ class StackProfile(base.Profile):
|
||||
self.stack_id = None
|
||||
|
||||
def heat(self):
|
||||
'''
|
||||
Construct heat client using the combined context.
|
||||
'''
|
||||
'''Construct heat client using the combined context.'''
|
||||
|
||||
if self.hc:
|
||||
return self.hc
|
||||
|
||||
@@ -69,9 +69,8 @@ class StackProfile(base.Profile):
|
||||
return self.hc
|
||||
|
||||
def do_validate(self, obj):
|
||||
'''
|
||||
Validate if the spec has provided reasonable info for stack creation.
|
||||
'''
|
||||
'''Validate if the spec has provided info for stack creation.'''
|
||||
|
||||
kwargs = {
|
||||
'stack_name': obj.name,
|
||||
'template': self.template,
|
||||
@@ -117,9 +116,8 @@ class StackProfile(base.Profile):
|
||||
reason=msg)
|
||||
|
||||
def do_create(self, obj):
|
||||
'''
|
||||
Create a stack using the given profile.
|
||||
'''
|
||||
'''Create a stack using the given profile.'''
|
||||
|
||||
kwargs = {
|
||||
'stack_name': obj.name,
|
||||
'template': self.template,
|
||||
@@ -160,7 +158,8 @@ class StackProfile(base.Profile):
|
||||
return True
|
||||
|
||||
def do_update(self, obj, new_profile):
|
||||
'''
|
||||
'''Perform update on object.
|
||||
|
||||
:param obj: the node object to operate on
|
||||
:param new_profile: the new profile used for updating
|
||||
'''
|
||||
|
||||
@@ -58,21 +58,20 @@ class EngineClient(object):
|
||||
return client.cast(ctxt, method, **kwargs)
|
||||
|
||||
def local_error_name(self, error):
|
||||
"""
|
||||
Returns the name of the error with any _Remote postfix removed.
|
||||
'''Returns the name of the error with any _Remote postfix removed.
|
||||
|
||||
:param error: Remote raised error to derive the name from.
|
||||
"""
|
||||
'''
|
||||
|
||||
error_name = error.__class__.__name__
|
||||
return error_name.split('_Remote')[0]
|
||||
|
||||
def ignore_error_named(self, error, name):
|
||||
"""
|
||||
Raises the error unless its local name matches the supplied name
|
||||
'''Raises the error unless its local name matches the supplied name
|
||||
|
||||
:param error: Remote raised error to derive the local name from.
|
||||
:param name: Name to compare local name to.
|
||||
"""
|
||||
'''
|
||||
if self.local_error_name(error) != name:
|
||||
raise error
|
||||
|
||||
@@ -130,14 +129,13 @@ class EngineClient(object):
|
||||
type_name=type_name))
|
||||
|
||||
def identify_cluster(self, ctxt, cluster_name):
|
||||
"""
|
||||
The identify_cluster method returns the full cluster identifier for a
|
||||
single, live cluster given the cluster name.
|
||||
'''Get the full cluster identifier for a single, live cluster given
|
||||
the cluster name.
|
||||
|
||||
:param ctxt: RPC context.
|
||||
:param cluster_name: Name of the cluster you want to see,
|
||||
or None to see all
|
||||
"""
|
||||
'''
|
||||
return self.call(ctxt, self.make_msg('identify_cluster',
|
||||
cluster_name=cluster_name))
|
||||
|
||||
|
||||
9
tox.ini
9
tox.ini
@@ -44,16 +44,11 @@ commands = python setup.py build_sphinx
|
||||
# F812 list comprehension redefines variable
|
||||
# H202 assertRaises Exception too broard
|
||||
# H233 Python 3.x incompatible use of print operator
|
||||
# H305 imports not grouped correctly
|
||||
# H307 like imports should be grouped together
|
||||
# H402 one line docstring needs punctuation
|
||||
# H404 multi line docstring should start with a summary
|
||||
# H405 multi line docstring summary not separated with an empty line
|
||||
# H803 no full stop at the end of the commit message
|
||||
# H904 Wrap long lines in parentheses instead of a backslash
|
||||
ignore = E251,E265,F402,F812,H202,H233,H305,H307,H402,H404,H405,H803,H904
|
||||
ignore = E251,E265,F402,F812,H202,H233,H307,H402
|
||||
show-source = true
|
||||
exclude=.venv,.git,.tox,dist,*openstack/common*,*lib/python*,*egg,tools,build
|
||||
exclude=.venv,.git,.tox,dist,*openstack/common*,*lib/python*,*egg,tools,build,*senlin/tests*
|
||||
max-complexity=20
|
||||
|
||||
[hacking]
|
||||
|
||||
Reference in New Issue
Block a user