congress/congress/harness.py

165 lines
6.1 KiB
Python

# Copyright (c) 2014 VMware, Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
import sys
from oslo_config import cfg
from oslo_log import log as logging
from congress.api import action_model
from congress.api import application
from congress.api import base as api_base
from congress.api import datasource_model
from congress.api import policy_model
from congress.api import router
from congress.api import row_model
from congress.api import rule_model
from congress.api import schema_model
from congress.api import status_model
from congress.api.system import driver_model
from congress.api import table_model
from congress.db import datasources as db_datasources
from congress.dse2 import datasource_manager as ds_manager
from congress.dse2 import dse_node
from congress import exception
from congress.policy_engines import agnostic
LOG = logging.getLogger(__name__)
def create2(node_id=None, bus_id=None, existing_node=None,
policy_engine=True, datasources=True, api=True):
"""Get Congress up.
Creates a DseNode if one is not provided and adds policy_engine,
datasources, api to that node.
:param node_id is node_id of DseNode to be created
:param bus_id is partition_id of DseNode to be created
:param existing_node is a DseNode (optional; in lieu of previous 2 params)
:param policy_engine controls whether policy_engine is included
:param datasources controls whether datasources are included
:param api controls whether API is included
:returns DseNode
"""
# create DseNode if existing_node not given
if existing_node is None:
assert (not (node_id is None or bus_id is None)),\
'params node_id and bus_id required.'
node = dse_node.DseNode(cfg.CONF, node_id, [], partition_id=bus_id)
else:
assert (node_id is None and bus_id is None),\
'params node_id and bus_id must be None when existing_node given.'
node = existing_node
# create services as required
services = {}
if datasources:
LOG.info("Registering congress datasource services on node %s",
node.node_id)
services['datasources'] = create_datasources(node)
services['ds_manager'] = ds_manager.DSManagerService(
api_base.DS_MANAGER_SERVICE_ID)
node.register_service(services['ds_manager'])
if policy_engine:
LOG.info("Registering congress PolicyEngine service on node %s",
node.node_id)
engine = create_policy_engine()
services[api_base.ENGINE_SERVICE_ID] = engine
node.register_service(engine)
initialize_policy_engine(engine)
if api:
LOG.info("Registering congress API service on node %s", node.node_id)
services['api'], services['api_service'] = create_api()
node.register_service(services['api_service'])
return services
def create_api():
"""Return service that encapsulates api logic for DSE2."""
# ResourceManager inherits from DataService
api_resource_mgr = application.ResourceManager()
models = create_api_models(api_resource_mgr)
router.APIRouterV1(api_resource_mgr, models)
return models, api_resource_mgr
def create_api_models(bus):
"""Create all the API models and return as a dictionary for DSE2."""
res = {}
res['api-policy'] = policy_model.PolicyModel('api-policy', bus=bus)
res['api-rule'] = rule_model.RuleModel('api-rule', bus=bus)
res['api-row'] = row_model.RowModel('api-row', bus=bus)
res['api-datasource'] = datasource_model.DatasourceModel(
'api-datasource', bus=bus)
res['api-schema'] = schema_model.SchemaModel('api-schema', bus=bus)
res['api-table'] = table_model.TableModel('api-table', bus=bus)
res['api-status'] = status_model.StatusModel('api-status', bus=bus)
res['api-action'] = action_model.ActionsModel('api-action', bus=bus)
res['api-system'] = driver_model.DatasourceDriverModel(
'api-system', bus=bus)
return res
def create_policy_engine():
"""Create policy engine and initialize it using the api models."""
engine = agnostic.DseRuntime(api_base.ENGINE_SERVICE_ID)
engine.debug_mode() # should take this out for production
return engine
def initialize_policy_engine(engine):
"""Initialize the policy engine using the API."""
# Load policies from database
engine.persistent_load_policies()
engine.create_default_policies()
engine.persistent_load_rules()
def create_datasources(bus):
"""Create and register datasource services ."""
if cfg.CONF.delete_missing_driver_datasources:
# congress server started with --delete-missing-driver-datasources
bus.delete_missing_driver_datasources()
datasources = db_datasources.get_datasources()
services = []
for ds in datasources:
LOG.info("create configured datasource service %s.", ds.name)
try:
service = bus.create_datasource_service(ds)
if service:
bus.register_service(service)
services.append(service)
except exception.DriverNotFound:
LOG.exception("Some datasources could not be loaded, start "
"congress server with "
"--delete-missing-driver-datasources option to "
"clean up stale datasources in DB.")
sys.exit(1)
except Exception:
LOG.exception("datasource %s creation failed. %s service may not "
"be running.", ds.name, ds.driver)
return services