basic OperationEngine service: Implement a runnable service

Implement a runnable service basic OperationEngine service.
I take creating a scheduled_operation for an example. To show
RPC call between api service and OperationEngine service.

Change-Id: I24038513bdb545567b308a6daeac7b0d86d5e29e
Closes-Bug: #1527097
This commit is contained in:
chenying 2015-12-21 17:10:30 +08:00
parent 62833b5d2b
commit bcaa976c74
14 changed files with 305 additions and 10 deletions

View File

@ -18,6 +18,7 @@ ENABLED_SERVICES+=,c-api,c-vol,c-sch,c-bak,horizon
#Add the smaug services
enable_service smaug-api
enable_service smaug-operationengine
#disable the default services you don't want to use
disable_service n-net

View File

@ -50,6 +50,7 @@ function configure_smaug_api {
iniset $SMAUG_API_CONF DEFAULT use_syslog $SYSLOG
echo "Configuring Smaug API Database"
iniset $SMAUG_API_CONF database connection `database_connection_url smaug`
iniset_rpc_backend smaug $SMAUG_API_CONF
setup_colorized_logging $SMAUG_API_CONF DEFAULT
echo "Configuring Smaug API colorized"
@ -113,6 +114,9 @@ if [[ "$Q_ENABLE_SMAUG" == "True" ]]; then
if is_service_enabled smaug-api; then
run_process smaug-api "$SMAUG_BIN_DIR/smaug-api --config-file $SMAUG_API_CONF"
fi
if is_service_enabled smaug-operationengine; then
run_process smaug-operationengine "$SMAUG_BIN_DIR/smaug-operationengine --config-file $SMAUG_API_CONF"
fi
fi
if [[ "$1" == "unstack" ]]; then
@ -120,5 +124,8 @@ if [[ "$Q_ENABLE_SMAUG" == "True" ]]; then
if is_service_enabled smaug-api; then
stop_process smaug-api
fi
if is_service_enabled smaug-operationengine; then
stop_process smaug-operationengine
fi
fi
fi

View File

@ -21,3 +21,11 @@
#auth_strategy = noauth
#log_dir = /var/log/
#rpc_backend = rabbit
#[database]
#connection = mysql+pymysql://root:stackdb@127.0.0.1/smaug?charset=utf8
#[oslo_messaging_rabbit]
#rabbit_userid = stackrabbit
#rabbit_password = stackqueue
#rabbit_hosts = 10.229.50.225

View File

@ -33,7 +33,7 @@ data_files =
console_scripts =
smaug-api = smaug.cmd.api:main
smaug-manage = smaug.cmd.manage:main
smaug-operationengine = smaug.cmd.operationengine:main
smaug.database.migration_backend =
sqlalchemy = oslo_db.sqlalchemy.migration

View File

@ -19,7 +19,7 @@ from webob import exc
from smaug.api.openstack import wsgi
from smaug.i18n import _LI
from smaug.operationengine import api as operationengine_api
LOG = logging.getLogger(__name__)
@ -28,6 +28,7 @@ class PlansController(wsgi.Controller):
"""The Plans API controller for the OpenStack API."""
def __init__(self):
self.operationengine_api = operationengine_api.API()
super(PlansController, self).__init__()
def show(self, req, id):

View File

@ -12,6 +12,7 @@
from smaug.api.openstack import ProjectMapper
from smaug.api.v1 import plans
from smaug.api.v1 import scheduled_operations
from smaug.wsgi import common as wsgi_common
@ -22,9 +23,13 @@ class APIRouter(wsgi_common.Router):
def __init__(self, mapper):
plans_resources = plans.create_resource()
scheduled_operation_resources = scheduled_operations.create_resource()
mapper.resource("plan", "plans",
controller=plans_resources,
collection={'detail': 'GET'},
member={'action': 'POST'})
mapper.resource("scheduled_operation", "scheduled_operations",
controller=scheduled_operation_resources,
collection={'detail': 'GET'},
member={'action': 'POST'})
super(APIRouter, self).__init__(mapper)

View File

@ -0,0 +1,100 @@
# 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.
"""The ScheduledOperations api."""
from oslo_log import log as logging
import webob
from webob import exc
from smaug.api.openstack import wsgi
from smaug.i18n import _LI
from smaug.operationengine import api as operationengine_api
LOG = logging.getLogger(__name__)
class ScheduledOperationsController(wsgi.Controller):
"""The ScheduledOperations API controller for the OpenStack API."""
def __init__(self):
self.operationengine_api = operationengine_api.API()
super(ScheduledOperationsController, self).__init__()
def show(self, req, id):
"""Return data about the given scheduled_operation."""
context = req.environ['smaug.context']
LOG.info(_LI("Show ScheduledOperation with id: %s"), id,
context=context)
# TODO(chenying)
return {'Smaug': "ScheduledOperations show."}
def delete(self, req, id):
"""Delete a scheduled_operation."""
context = req.environ['smaug.context']
LOG.info(_LI("Delete ScheduledOperations with id: %s"), id,
context=context)
# TODO(chenying)
return webob.Response(status_int=202)
def index(self, req):
"""Returns a summary list of ScheduledOperations."""
# TODO(chenying)
return {'scheduled_operation': "ScheduledOperations index."}
def detail(self, req):
"""Returns a detailed list of ScheduledOperations."""
# TODO(chenying)
return {'scheduled_operation': "ScheduledOperations detail."}
def create(self, req, body):
"""Creates a new ScheduledOperation."""
LOG.debug('Create ScheduledOperations request body: %s', body)
context = req.environ['smaug.context']
request_spec = {'resource': 'ScheduledOperations',
'method': 'create'}
self.operationengine_api.create_scheduled_operation(context,
request_spec)
LOG.debug('Create ScheduledOperations request context: %s', context)
# TODO(chenying)
return {'scheduled_operation': "Create a ScheduledOperation."}
def update(self, req, id, body):
"""Update a scheduled_operation."""
context = req.environ['smaug.context']
if not body:
raise exc.HTTPUnprocessableEntity()
if 'scheduled_operation' not in body:
raise exc.HTTPUnprocessableEntity()
scheduled_operation = body['scheduled_operation']
LOG.info(_LI("Update ScheduledOperation : %s"), scheduled_operation,
context=context)
return {'scheduled_operation': "Update a ScheduledOperation."}
def create_resource():
return wsgi.Resource(ScheduledOperationsController())

View File

@ -0,0 +1,42 @@
#!/usr/bin/env python
# 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.
"""Starter script for smaug OperationEngine."""
import eventlet
eventlet.monkey_patch()
import sys
from oslo_config import cfg
from oslo_log import log as logging
from smaug import i18n
i18n.enable_lazy()
# Need to register global_opts
from smaug.common import config # noqa
from smaug import service
from smaug import version
CONF = cfg.CONF
def main():
CONF(sys.argv[1:], project='smaug',
version=version.version_string())
logging.setup(CONF, "smaug")
server = service.Service.create(binary='smaug-operationengine')
service.serve(server)
service.wait()

View File

@ -49,12 +49,12 @@ global_opts = [
default=60,
help='Maximum time since last check-in for a service to be '
'considered up'),
cfg.StrOpt('scheduler_topic',
default='Smaug-scheduler',
help='The topic that scheduler nodes listen on'),
cfg.StrOpt('scheduler_manager',
default='Smaug.scheduler.manager.SchedulerManager',
help='Full class name for the Manager for scheduler'),
cfg.StrOpt('operationengine_topic',
default='smaug-operationengine',
help='The topic that OperationEngine nodes listen on'),
cfg.StrOpt('operationengine_manager',
default='smaug.operationengine.manager.OperationEngineManager',
help='Full class name for the Manager for OperationEngine'),
cfg.StrOpt('host',
default=socket.gethostname(),
help='Name of this node. This can be an opaque identifier. '

View File

View File

@ -0,0 +1,38 @@
# 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.
"""Handles all requests relating to OperationEngine."""
from oslo_config import cfg
from oslo_log import log as logging
from smaug.db import base
from smaug.operationengine import rpcapi as operationengine_rpcapi
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
class API(base.Base):
"""API for interacting with the OperationEngine manager."""
def __init__(self, db_driver=None):
self.operationengine_rpcapi = operationengine_rpcapi.\
OperationEngineAPI()
super(API, self).__init__(db_driver)
def create_scheduled_operation(self, context, request_spec):
self.operationengine_rpcapi.create_scheduled_operation(context,
request_spec)

View File

@ -0,0 +1,42 @@
# 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.
"""
OperationEngine Service
"""
from oslo_config import cfg
from oslo_log import log as logging
import oslo_messaging as messaging
from smaug import manager
CONF = cfg.CONF
LOG = logging.getLogger(__name__)
class OperationEngineManager(manager.Manager):
"""Smaug OperationEngine Manager."""
RPC_API_VERSION = '1.0'
target = messaging.Target(version=RPC_API_VERSION)
def __init__(self, service_name=None,
*args, **kwargs):
super(OperationEngineManager, self).__init__(*args, **kwargs)
def create_scheduled_operation(self, context, request_spec=None):
LOG.debug("Received a rpc call from a api service."
"request_spec:%s", request_spec)

View File

@ -0,0 +1,51 @@
# Copyright 2012, Red Hat, Inc.
#
# 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.
"""
Client side of the OperationEngine manager RPC API.
"""
from oslo_config import cfg
import oslo_messaging as messaging
from oslo_serialization import jsonutils
from smaug import rpc
CONF = cfg.CONF
class OperationEngineAPI(object):
"""Client side of the OperationEngine rpc API.
API version history:
1.0 - Initial version.
"""
RPC_API_VERSION = '1.0'
def __init__(self):
super(OperationEngineAPI, self).__init__()
target = messaging.Target(topic=CONF.operationengine_topic,
version=self.RPC_API_VERSION)
self.client = rpc.get_client(target, version_cap=None)
def create_scheduled_operation(self, ctxt, request_spec=None):
request_spec_p = jsonutils.to_primitive(request_spec)
cctxt = self.client.prepare(version='1.0')
return cctxt.cast(
ctxt,
'create_scheduled_operation',
request_spec=request_spec_p)

View File

@ -48,7 +48,7 @@ service_opts = [
cfg.IntOpt('periodic_fuzzy_delay',
default=60,
help='Range, in seconds, to randomly delay when starting the'
' periodic task scheduler to reduce stampeding.'
' periodic task OperationEngine to reduce stampeding.'
' (Disable by setting to 0)'),
cfg.StrOpt('osapi_smaug_listen',
default="0.0.0.0",