Create a new heat.rpc package

The definition of the RPC API is common between the engine (server) and the
clients, so move the client and common definitions out of the heat.engine
package.

Change-Id: I5fd2ba26f09c86ba1adecab4f9e06e69a694fe90
Signed-off-by: Zane Bitter <zbitter@redhat.com>
changes/13/17213/2
Zane Bitter 10 years ago
parent cd2fd324a0
commit 97135b8f60
  1. 6
      heat/api/cfn/v1/stacks.py
  2. 6
      heat/api/cfn/v1/waitcondition.py
  3. 6
      heat/api/cloudwatch/watch.py
  4. 6
      heat/api/openstack/v1/events.py
  5. 6
      heat/api/openstack/v1/resources.py
  6. 50
      heat/api/openstack/v1/stacks.py
  7. 118
      heat/engine/api.py
  8. 13
      heat/engine/watchrule.py
  9. 0
      heat/rpc/__init__.py
  10. 125
      heat/rpc/api.py
  11. 4
      heat/rpc/client.py
  12. 2
      heat/tests/test_api_cloudwatch.py
  13. 6
      heat/tests/test_rpc_client.py

@ -25,9 +25,9 @@ import errno
from heat.api.aws import exception
from heat.api.aws import utils as api_utils
from heat.common import wsgi
from heat.engine import rpcapi as engine_rpcapi
from heat.rpc import client as rpc_client
from heat.common import template_format
import heat.engine.api as engine_api
from heat.rpc import api as engine_api
from heat.common import identifier
import heat.openstack.common.rpc.common as rpc_common
@ -47,7 +47,7 @@ class StackController(object):
def __init__(self, options):
self.options = options
self.engine_rpcapi = engine_rpcapi.EngineAPI()
self.engine_rpcapi = rpc_client.EngineClient()
@staticmethod
def _id_format(resp):

@ -19,7 +19,7 @@ from webob.exc import Response
from heat.common import wsgi
from heat.common import context
from heat.engine import rpcapi as engine_rpcapi
from heat.rpc import client as rpc_client
from heat.openstack.common import rpc
@ -40,11 +40,11 @@ def json_error(http_status, message):
class WaitConditionController:
def __init__(self, options):
self.options = options
self.engine_rpcapi = engine_rpcapi.EngineAPI()
self.engine = rpc_client.EngineClient()
def update_waitcondition(self, req, body, stack_id, resource_name):
con = req.context
[error, metadata] = self.engine_rpcapi.metadata_update(con,
[error, metadata] = self.engine.metadata_update(con,
stack_id=stack_id,
resource_name=resource_name,
metadata=body)

@ -19,8 +19,8 @@ endpoint for heat AWS-compatible CloudWatch API
from heat.api.aws import exception
from heat.api.aws import utils as api_utils
from heat.common import wsgi
from heat.engine import rpcapi as engine_rpcapi
import heat.engine.api as engine_api
from heat.rpc import client as rpc_client
from heat.rpc import api as engine_api
import heat.openstack.common.rpc.common as rpc_common
from heat.openstack.common import log as logging
@ -37,7 +37,7 @@ class WatchController(object):
def __init__(self, options):
self.options = options
self.engine_rpcapi = engine_rpcapi.EngineAPI()
self.engine_rpcapi = rpc_client.EngineClient()
@staticmethod
def _reformat_dimensions(dims):

@ -18,9 +18,9 @@ from webob import exc
from heat.api.openstack.v1 import util
from heat.common import wsgi
from heat.engine import api as engine_api
from heat.rpc import api as engine_api
from heat.common import identifier
from heat.engine import rpcapi as engine_rpcapi
from heat.rpc import client as rpc_client
import heat.openstack.common.rpc.common as rpc_common
from heat.openstack.common.gettextutils import _
@ -68,7 +68,7 @@ class EventController(object):
def __init__(self, options):
self.options = options
self.engine = engine_rpcapi.EngineAPI()
self.engine = rpc_client.EngineClient()
def _event_list(self, req, identity,
filter_func=lambda e: True, detail=False):

@ -17,9 +17,9 @@ import itertools
from heat.api.openstack.v1 import util
from heat.common import wsgi
from heat.engine import api as engine_api
from heat.rpc import api as engine_api
from heat.common import identifier
from heat.engine import rpcapi as engine_rpcapi
from heat.rpc import client as rpc_client
import heat.openstack.common.rpc.common as rpc_common
@ -54,7 +54,7 @@ class ResourceController(object):
def __init__(self, options):
self.options = options
self.engine = engine_rpcapi.EngineAPI()
self.engine = rpc_client.EngineClient()
@util.identified_stack
def index(self, req, identity):

@ -27,8 +27,8 @@ from webob import exc
from heat.api.openstack.v1 import util
from heat.common import wsgi
from heat.common import template_format
from heat.engine import api as engine_api
from heat.engine import rpcapi as engine_rpcapi
from heat.rpc import api as engine_api
from heat.rpc import client as rpc_client
import heat.openstack.common.rpc.common as rpc_common
from heat.openstack.common import log as logging
@ -164,7 +164,7 @@ class StackController(object):
def __init__(self, options):
self.options = options
self.engine_rpcapi = engine_rpcapi.EngineAPI()
self.engine = rpc_client.EngineClient()
def default(self, req, **args):
raise exc.HTTPNotFound()
@ -176,7 +176,7 @@ class StackController(object):
"""
try:
stack_list = self.engine_rpcapi.list_stacks(req.context)
stack_list = self.engine.list_stacks(req.context)
except rpc_common.RemoteError as ex:
return util.remote_error(ex, True)
@ -202,11 +202,11 @@ class StackController(object):
data = InstantiationData(body)
try:
result = self.engine_rpcapi.create_stack(req.context,
data.stack_name(),
data.template(),
data.user_params(),
data.args())
result = self.engine.create_stack(req.context,
data.stack_name(),
data.template(),
data.user_params(),
data.args())
except rpc_common.RemoteError as ex:
return util.remote_error(ex, True)
@ -222,8 +222,8 @@ class StackController(object):
"""
try:
identity = self.engine_rpcapi.identify_stack(req.context,
stack_name)
identity = self.engine.identify_stack(req.context,
stack_name)
except rpc_common.RemoteError as ex:
return util.remote_error(ex)
@ -240,8 +240,8 @@ class StackController(object):
"""
try:
stack_list = self.engine_rpcapi.show_stack(req.context,
identity)
stack_list = self.engine.show_stack(req.context,
identity)
except rpc_common.RemoteError as ex:
return util.remote_error(ex)
@ -259,8 +259,8 @@ class StackController(object):
"""
try:
templ = self.engine_rpcapi.get_template(req.context,
identity)
templ = self.engine.get_template(req.context,
identity)
except rpc_common.RemoteError as ex:
return util.remote_error(ex)
@ -278,11 +278,11 @@ class StackController(object):
data = InstantiationData(body)
try:
res = self.engine_rpcapi.update_stack(req.context,
identity,
data.template(),
data.user_params(),
data.args())
res = self.engine.update_stack(req.context,
identity,
data.template(),
data.user_params(),
data.args())
except rpc_common.RemoteError as ex:
return util.remote_error(ex)
@ -298,9 +298,9 @@ class StackController(object):
"""
try:
res = self.engine_rpcapi.delete_stack(req.context,
identity,
cast=False)
res = self.engine.delete_stack(req.context,
identity,
cast=False)
except rpc_common.RemoteError as ex:
return util.remote_error(ex)
@ -320,8 +320,8 @@ class StackController(object):
data = InstantiationData(body)
try:
result = self.engine_rpcapi.validate_template(req.context,
data.template())
result = self.engine.validate_template(req.context,
data.template())
except rpc_common.RemoteError as ex:
return util.remote_error(ex, True)

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from heat.rpc.api import *
from heat.openstack.common import timeutils
from heat.engine import parser
from heat.engine import template
@ -21,8 +22,6 @@ from heat.openstack.common import log as logging
logger = logging.getLogger('heat.engine.manager')
PARAM_KEYS = (PARAM_TIMEOUT, ) = ('timeout_mins', )
def extract_args(params):
'''
@ -41,33 +40,6 @@ def extract_args(params):
return kwargs
STACK_KEYS = (
STACK_NAME, STACK_ID,
STACK_CREATION_TIME, STACK_UPDATED_TIME, STACK_DELETION_TIME,
STACK_NOTIFICATION_TOPICS,
STACK_DESCRIPTION, STACK_TMPL_DESCRIPTION,
STACK_PARAMETERS, STACK_OUTPUTS,
STACK_STATUS, STACK_STATUS_DATA, STACK_CAPABILITIES,
STACK_DISABLE_ROLLBACK, STACK_TIMEOUT,
) = (
'stack_name', 'stack_identity',
'creation_time', 'updated_time', 'deletion_time',
'notification_topics',
'description', 'template_description',
'parameters', 'outputs',
'stack_status', 'stack_status_reason', 'capabilities',
'disable_rollback', 'timeout_mins'
)
STACK_OUTPUT_KEYS = (
OUTPUT_DESCRIPTION,
OUTPUT_KEY, OUTPUT_VALUE,
) = (
'description',
'output_key', 'output_value',
)
def format_stack_outputs(stack, outputs):
'''
Return a representation of the given output template for the given stack
@ -110,19 +82,6 @@ def format_stack(stack):
return info
RES_KEYS = (
RES_DESCRIPTION, RES_UPDATED_TIME,
RES_NAME, RES_PHYSICAL_ID, RES_METADATA,
RES_STATUS, RES_STATUS_DATA, RES_TYPE,
RES_ID, RES_STACK_ID, RES_STACK_NAME,
) = (
'description', 'updated_time',
'logical_resource_id', 'physical_resource_id', 'metadata',
'resource_status', 'resource_status_reason', 'resource_type',
'resource_identity', STACK_ID, STACK_NAME,
)
def format_stack_resource(resource, detail=True):
'''
Return a representation of the given resource that matches the API output
@ -149,23 +108,6 @@ def format_stack_resource(resource, detail=True):
return res
EVENT_KEYS = (
EVENT_ID,
EVENT_STACK_ID, EVENT_STACK_NAME,
EVENT_TIMESTAMP,
EVENT_RES_NAME, EVENT_RES_PHYSICAL_ID,
EVENT_RES_STATUS, EVENT_RES_STATUS_DATA, EVENT_RES_TYPE,
EVENT_RES_PROPERTIES,
) = (
'event_identity',
STACK_ID, STACK_NAME,
"event_time",
RES_NAME, RES_PHYSICAL_ID,
RES_STATUS, RES_STATUS_DATA, RES_TYPE,
'resource_properties',
)
def format_event(event):
stack_identifier = event.stack.identifier()
@ -185,56 +127,6 @@ def format_event(event):
return result
# This is the representation of a watch we expose to the API via RPC
WATCH_KEYS = (
WATCH_ACTIONS_ENABLED, WATCH_ALARM_ACTIONS, WATCH_TOPIC,
WATCH_UPDATED_TIME, WATCH_DESCRIPTION, WATCH_NAME,
WATCH_COMPARISON, WATCH_DIMENSIONS, WATCH_PERIODS,
WATCH_INSUFFICIENT_ACTIONS, WATCH_METRIC_NAME, WATCH_NAMESPACE,
WATCH_OK_ACTIONS, WATCH_PERIOD, WATCH_STATE_REASON,
WATCH_STATE_REASON_DATA, WATCH_STATE_UPDATED_TIME, WATCH_STATE_VALUE,
WATCH_STATISTIC, WATCH_THRESHOLD, WATCH_UNIT, WATCH_STACK_ID
) = (
'actions_enabled', 'actions', 'topic',
'updated_time', 'description', 'name',
'comparison', 'dimensions', 'periods',
'insufficient_actions', 'metric_name', 'namespace',
'ok_actions', 'period', 'state_reason',
'state_reason_data', 'state_updated_time', 'state_value',
'statistic', 'threshold', 'unit', 'stack_id')
# Alternate representation of a watch rule to align with DB format
# FIXME : These align with AWS naming for compatibility with the
# current cfn-push-stats & metadata server, fix when we've ported
# cfn-push-stats to use the Cloudwatch server and/or moved metric
# collection into ceilometer, these should just be WATCH_KEYS
# or each field should be stored separately in the DB watch_data
# table if we stick to storing watch data in the heat DB
WATCH_RULE_KEYS = (
RULE_ACTIONS_ENABLED, RULE_ALARM_ACTIONS, RULE_TOPIC,
RULE_UPDATED_TIME, RULE_DESCRIPTION, RULE_NAME,
RULE_COMPARISON, RULE_DIMENSIONS, RULE_PERIODS,
RULE_INSUFFICIENT_ACTIONS, RULE_METRIC_NAME, RULE_NAMESPACE,
RULE_OK_ACTIONS, RULE_PERIOD, RULE_STATE_REASON,
RULE_STATE_REASON_DATA, RULE_STATE_UPDATED_TIME, RULE_STATE_VALUE,
RULE_STATISTIC, RULE_THRESHOLD, RULE_UNIT, RULE_STACK_NAME
) = (
'ActionsEnabled', 'AlarmActions', 'AlarmArn',
'AlarmConfigurationUpdatedTimestamp', 'AlarmDescription', 'AlarmName',
'ComparisonOperator', 'Dimensions', 'EvaluationPeriods',
'InsufficientDataActions', 'MetricName', 'Namespace',
'OKActions', 'Period', 'StateReason',
'StateReasonData', 'StateUpdatedTimestamp', 'StateValue',
'Statistic', 'Threshold', 'Unit', 'StackName')
WATCH_STATES = (WATCH_STATE_OK, WATCH_STATE_ALARM, WATCH_STATE_NODATA
) = (watchrule.WatchRule.NORMAL,
watchrule.WatchRule.ALARM,
watchrule.WatchRule.NODATA)
def format_watch(watch):
result = {
@ -266,14 +158,6 @@ def format_watch(watch):
return result
WATCH_DATA_KEYS = (
WATCH_DATA_ALARM, WATCH_DATA_METRIC, WATCH_DATA_TIME,
WATCH_DATA_NAMESPACE, WATCH_DATA
) = (
'watch_name', 'metric_name', 'timestamp',
'namespace', 'data')
def format_watch_data(wd):
# Demangle DB format data into something more easily used in the API

@ -20,6 +20,7 @@ from heat.openstack.common import timeutils
from heat.engine import timestamp
from heat.db import api as db_api
from heat.engine import parser
from heat.rpc import api as rpc_api
from heat.common import context as ctxtlib
import eventlet
@ -28,9 +29,15 @@ greenpool = eventlet.GreenPool()
class WatchRule(object):
WATCH_STATES = (ALARM, NORMAL, NODATA
) = ('ALARM', 'NORMAL', 'NODATA')
WATCH_STATES = (
ALARM,
NORMAL,
NODATA
) = (
rpc_api.WATCH_STATE_ALARM,
rpc_api.WATCH_STATE_OK,
rpc_api.WATCH_STATE_NODATA
)
ACTION_MAP = {ALARM: 'AlarmActions',
NORMAL: 'OKActions',
NODATA: 'InsufficientDataActions'}

@ -0,0 +1,125 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# 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.
PARAM_KEYS = (PARAM_TIMEOUT, ) = ('timeout_mins', )
STACK_KEYS = (
STACK_NAME, STACK_ID,
STACK_CREATION_TIME, STACK_UPDATED_TIME, STACK_DELETION_TIME,
STACK_NOTIFICATION_TOPICS,
STACK_DESCRIPTION, STACK_TMPL_DESCRIPTION,
STACK_PARAMETERS, STACK_OUTPUTS,
STACK_STATUS, STACK_STATUS_DATA, STACK_CAPABILITIES,
STACK_DISABLE_ROLLBACK, STACK_TIMEOUT,
) = (
'stack_name', 'stack_identity',
'creation_time', 'updated_time', 'deletion_time',
'notification_topics',
'description', 'template_description',
'parameters', 'outputs',
'stack_status', 'stack_status_reason', 'capabilities',
'disable_rollback', 'timeout_mins'
)
STACK_OUTPUT_KEYS = (
OUTPUT_DESCRIPTION,
OUTPUT_KEY, OUTPUT_VALUE,
) = (
'description',
'output_key', 'output_value',
)
RES_KEYS = (
RES_DESCRIPTION, RES_UPDATED_TIME,
RES_NAME, RES_PHYSICAL_ID, RES_METADATA,
RES_STATUS, RES_STATUS_DATA, RES_TYPE,
RES_ID, RES_STACK_ID, RES_STACK_NAME,
) = (
'description', 'updated_time',
'logical_resource_id', 'physical_resource_id', 'metadata',
'resource_status', 'resource_status_reason', 'resource_type',
'resource_identity', STACK_ID, STACK_NAME,
)
EVENT_KEYS = (
EVENT_ID,
EVENT_STACK_ID, EVENT_STACK_NAME,
EVENT_TIMESTAMP,
EVENT_RES_NAME, EVENT_RES_PHYSICAL_ID,
EVENT_RES_STATUS, EVENT_RES_STATUS_DATA, EVENT_RES_TYPE,
EVENT_RES_PROPERTIES,
) = (
'event_identity',
STACK_ID, STACK_NAME,
"event_time",
RES_NAME, RES_PHYSICAL_ID,
RES_STATUS, RES_STATUS_DATA, RES_TYPE,
'resource_properties',
)
# This is the representation of a watch we expose to the API via RPC
WATCH_KEYS = (
WATCH_ACTIONS_ENABLED, WATCH_ALARM_ACTIONS, WATCH_TOPIC,
WATCH_UPDATED_TIME, WATCH_DESCRIPTION, WATCH_NAME,
WATCH_COMPARISON, WATCH_DIMENSIONS, WATCH_PERIODS,
WATCH_INSUFFICIENT_ACTIONS, WATCH_METRIC_NAME, WATCH_NAMESPACE,
WATCH_OK_ACTIONS, WATCH_PERIOD, WATCH_STATE_REASON,
WATCH_STATE_REASON_DATA, WATCH_STATE_UPDATED_TIME, WATCH_STATE_VALUE,
WATCH_STATISTIC, WATCH_THRESHOLD, WATCH_UNIT, WATCH_STACK_ID
) = (
'actions_enabled', 'actions', 'topic',
'updated_time', 'description', 'name',
'comparison', 'dimensions', 'periods',
'insufficient_actions', 'metric_name', 'namespace',
'ok_actions', 'period', 'state_reason',
'state_reason_data', 'state_updated_time', 'state_value',
'statistic', 'threshold', 'unit', 'stack_id')
# Alternate representation of a watch rule to align with DB format
# FIXME : These align with AWS naming for compatibility with the
# current cfn-push-stats & metadata server, fix when we've ported
# cfn-push-stats to use the Cloudwatch server and/or moved metric
# collection into ceilometer, these should just be WATCH_KEYS
# or each field should be stored separately in the DB watch_data
# table if we stick to storing watch data in the heat DB
WATCH_RULE_KEYS = (
RULE_ACTIONS_ENABLED, RULE_ALARM_ACTIONS, RULE_TOPIC,
RULE_UPDATED_TIME, RULE_DESCRIPTION, RULE_NAME,
RULE_COMPARISON, RULE_DIMENSIONS, RULE_PERIODS,
RULE_INSUFFICIENT_ACTIONS, RULE_METRIC_NAME, RULE_NAMESPACE,
RULE_OK_ACTIONS, RULE_PERIOD, RULE_STATE_REASON,
RULE_STATE_REASON_DATA, RULE_STATE_UPDATED_TIME, RULE_STATE_VALUE,
RULE_STATISTIC, RULE_THRESHOLD, RULE_UNIT, RULE_STACK_NAME
) = (
'ActionsEnabled', 'AlarmActions', 'AlarmArn',
'AlarmConfigurationUpdatedTimestamp', 'AlarmDescription', 'AlarmName',
'ComparisonOperator', 'Dimensions', 'EvaluationPeriods',
'InsufficientDataActions', 'MetricName', 'Namespace',
'OKActions', 'Period', 'StateReason',
'StateReasonData', 'StateUpdatedTimestamp', 'StateValue',
'Statistic', 'Threshold', 'Unit', 'StackName')
WATCH_STATES = (
WATCH_STATE_OK, WATCH_STATE_ALARM, WATCH_STATE_NODATA
) = (
'NORMAL', 'ALARM', 'NODATA',
)
WATCH_DATA_KEYS = (
WATCH_DATA_ALARM, WATCH_DATA_METRIC, WATCH_DATA_TIME,
WATCH_DATA_NAMESPACE, WATCH_DATA
) = (
'watch_name', 'metric_name', 'timestamp',
'namespace', 'data'
)

@ -40,7 +40,7 @@ def _engine_topic(topic, ctxt, host):
return rpc.queue_get_for(ctxt, topic, host)
class EngineAPI(heat.openstack.common.rpc.proxy.RpcProxy):
class EngineClient(heat.openstack.common.rpc.proxy.RpcProxy):
'''Client side of the heat engine rpc API.
API version history:
@ -51,7 +51,7 @@ class EngineAPI(heat.openstack.common.rpc.proxy.RpcProxy):
BASE_RPC_API_VERSION = '1.0'
def __init__(self):
super(EngineAPI, self).__init__(
super(EngineClient, self).__init__(
topic=FLAGS.engine_topic,
default_version=self.BASE_RPC_API_VERSION)

@ -33,7 +33,7 @@ import heat.openstack.common.rpc.common as rpc_common
from heat.common.wsgi import Request
from heat.api.aws import exception
import heat.api.cloudwatch.watch as watches
import heat.engine.api as engine_api
from heat.rpc import api as engine_api
@attr(tag=['unit', 'api-cloudwatch', 'WatchController'])

@ -15,7 +15,7 @@
# under the License.
"""
Unit Tests for heat.engine.rpcapi
Unit Tests for heat.rpc.client
"""
@ -25,7 +25,7 @@ import unittest
from heat.common import config
from heat.common import context
from heat.engine import rpcapi as engine_rpcapi
from heat.rpc import client as rpc_client
from heat.openstack.common import cfg
from heat.openstack.common import rpc
@ -54,7 +54,7 @@ class EngineRpcAPITestCase(unittest.TestCase):
rpcapi_class = kwargs['rpcapi_class']
del kwargs['rpcapi_class']
else:
rpcapi_class = engine_rpcapi.EngineAPI
rpcapi_class = rpc_client.EngineClient
rpcapi = rpcapi_class()
expected_retval = 'foo' if method == 'call' else None
Loading…
Cancel
Save