diff --git a/devstack/lib/tacker b/devstack/lib/tacker index 130d61f32..ded9e0032 100644 --- a/devstack/lib/tacker +++ b/devstack/lib/tacker @@ -14,7 +14,7 @@ # - configure_tacker # - create_tacker_accounts # - init_tacker -# - start_tacker_api +# - start_tacker # - tacker_horizon_install # - tacker_create_initial_network @@ -144,7 +144,7 @@ function install_tacker { setup_develop $TACKER_DIR } -function start_tacker_api { +function start_tacker { local cfg_file_options="--config-file $TACKER_CONF" local service_port=$TACKER_PORT local service_protocol=$TACKER_PROTOCOL @@ -165,11 +165,14 @@ function start_tacker_api { if is_service_enabled tls-proxy; then start_tls_proxy '*' $TACKER_PORT $TACKER_HOST $TACKER_PORT_INT & fi + # Start tacker conductor + run_process tacker-conductor "$TACKER_BIN_DIR/tacker-conductor $cfg_file_options" } # stop_tacker() - Stop running processes (non-screen) function stop_tacker { stop_process tacker + stop_process tacker-conductor } # cleanup_tacker() - Remove residual data files, anything left over from previous diff --git a/devstack/plugin.sh b/devstack/plugin.sh index c989d8562..3c8584aa1 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -25,8 +25,8 @@ if is_service_enabled tacker; then # Initialize and start the tacker service echo_summary "Initializing Tacker" init_tacker - echo_summary "Starting Tacker API" - start_tacker_api + echo_summary "Starting Tacker API and conductor" + start_tacker echo_summary "Installing tacker horizon" tacker_horizon_install if [[ "${TACKER_MODE}" == "all" ]]; then diff --git a/devstack/settings b/devstack/settings index de356cf55..5865cc2da 100644 --- a/devstack/settings +++ b/devstack/settings @@ -19,7 +19,8 @@ if [ "${TACKER_MODE}" == "all" ]; then enable_service neutron enable_service tacker - + # enable tacker-conductor will make systemctl enable conductor service + enable_service tacker-conductor # tacker-horizon isn't installable from pip LIBS_FROM_GIT=tacker-horizon @@ -42,7 +43,7 @@ if [ "${TACKER_MODE}" == "all" ]; then NETWORK_GATEWAY1=${NETWORK_GATEWAY1:-10.10.1.1} elif [ "${TACKER_MODE}" == "standalone" ]; then # set the enabled services here. This will need tacker devstack plugin put as the last one in local.conf - ENABLED_SERVICES=key,horizon,tacker,mysql,dstat,barbican,mistral,mistral-api,mistral-engine,mistral-executor,mistral-event-engine + ENABLED_SERVICES=key,horizon,tacker,tacker-conductor,mysql,dstat,barbican,mistral,mistral-api,mistral-engine,mistral-executor,mistral-event-engine else die $LINENO "invalid value: $TACKER_MODE for TACKER_MODE" fi diff --git a/tacker/common/topics.py b/tacker/common/topics.py index 0a5ac2706..cc36d4e80 100644 --- a/tacker/common/topics.py +++ b/tacker/common/topics.py @@ -12,3 +12,4 @@ TOPIC_ACTION_KILL = 'KILL_ACTION' +TOPIC_CONDUCTOR = 'TACKER_CONDUCTOR' diff --git a/tacker/conductor/conductor_server.py b/tacker/conductor/conductor_server.py index 5003b2171..be632e813 100644 --- a/tacker/conductor/conductor_server.py +++ b/tacker/conductor/conductor_server.py @@ -19,11 +19,20 @@ from oslo_config import cfg from oslo_log import log as logging import oslo_messaging from oslo_service import service +from oslo_utils import timeutils +from sqlalchemy.orm import exc as orm_exc +from tacker.common import topics +from tacker import context as t_context +from tacker.db.common_services import common_services_db +from tacker.db.nfvo import nfvo_db +from tacker.extensions import nfvo from tacker import manager +from tacker.plugins.common import constants from tacker import service as tacker_service from tacker import version + LOG = logging.getLogger(__name__) @@ -35,9 +44,27 @@ class Conductor(manager.Manager): self.conf = cfg.CONF super(Conductor, self).__init__(host=self.conf.host) - -def register_opts(conf): - pass + def update_vim(self, context, vim_id, status): + t_admin_context = t_context.get_admin_context() + update_time = timeutils.utcnow() + with t_admin_context.session.begin(subtransactions=True): + try: + query = t_admin_context.session.query(nfvo_db.Vim) + query.filter( + nfvo_db.Vim.id == vim_id).update( + {'status': status, + 'updated_at': update_time}) + except orm_exc.NoResultFound: + raise nfvo.VimNotFoundException(vim_id=vim_id) + event_db = common_services_db.Event( + resource_id=vim_id, + resource_type=constants.RES_TYPE_VIM, + resource_state=status, + event_details="", + event_type=constants.RES_EVT_MONITOR, + timestamp=update_time) + t_admin_context.session.add(event_db) + return status def init(args, **kwargs): @@ -52,7 +79,6 @@ def init(args, **kwargs): def main(manager='tacker.conductor.conductor_server.Conductor'): - register_opts(cfg.CONF) init(sys.argv[1:]) logging.setup(cfg.CONF, "tacker") oslo_messaging.set_transport_defaults(control_exchange='tacker') @@ -60,6 +86,6 @@ def main(manager='tacker.conductor.conductor_server.Conductor'): cfg.CONF.log_opt_values(LOG, logging.DEBUG) server = tacker_service.Service.create( binary='tacker-conductor', - topic='tacker_conductor', + topic=topics.TOPIC_CONDUCTOR, manager=manager) service.launch(cfg.CONF, server).wait() diff --git a/tacker/conductor/conductorrpc/vim_monitor_rpc.py b/tacker/conductor/conductorrpc/vim_monitor_rpc.py index e69de29bb..50ce7ae32 100644 --- a/tacker/conductor/conductorrpc/vim_monitor_rpc.py +++ b/tacker/conductor/conductorrpc/vim_monitor_rpc.py @@ -0,0 +1,30 @@ +# Copyright 2017 OpenStack Foundation +# 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. + +import oslo_messaging + +from tacker.common import topics + + +class VIMUpdateRPC(object): + + target = oslo_messaging.Target( + exchange='tacker', + topic=topics.TOPIC_CONDUCTOR, + fanout=False, + version='1.0') + + def update_vim(self, context, **kwargs): + pass diff --git a/tacker/db/common_services/common_services_db.py b/tacker/db/common_services/common_services_db.py index 3e626994c..33a594824 100644 --- a/tacker/db/common_services/common_services_db.py +++ b/tacker/db/common_services/common_services_db.py @@ -15,22 +15,9 @@ # under the License. import sqlalchemy as sa -from sqlalchemy.orm import exc as orm_exc -from oslo_log import log as logging - -from tacker.common import log -from tacker.db import db_base from tacker.db import model_base from tacker.db import types -from tacker.extensions import common_services -from tacker import manager - - -LOG = logging.getLogger(__name__) - -EVENT_ATTRIBUTES = ('id', 'resource_id', 'resource_type', 'resource_state', - 'timestamp', 'event_type', 'event_details') class Event(model_base.BASE): @@ -42,58 +29,3 @@ class Event(model_base.BASE): timestamp = sa.Column(sa.DateTime, nullable=False) event_type = sa.Column(sa.String(64), nullable=False) event_details = sa.Column(types.Json) - - -class CommonServicesPluginDb(common_services.CommonServicesPluginBase, - db_base.CommonDbMixin): - - def __init__(self): - super(CommonServicesPluginDb, self).__init__() - - @property - def _core_plugin(self): - return manager.TackerManager.get_plugin() - - def _make_event_dict(self, event_db, fields=None): - res = dict((key, event_db[key]) for key in EVENT_ATTRIBUTES) - return self._fields(res, fields) - - def _fields(self, resource, fields): - if fields: - return dict(((key, item) for key, item in resource.items() - if key in fields)) - return resource - - @log.log - def create_event(self, context, res_id, res_type, res_state, evt_type, - tstamp, details=""): - try: - with context.session.begin(subtransactions=True): - event_db = Event( - resource_id=res_id, - resource_type=res_type, - resource_state=res_state, - event_details=details, - event_type=evt_type, - timestamp=tstamp) - context.session.add(event_db) - except Exception as e: - LOG.exception(_("create event error: %s"), str(e)) - raise common_services.EventCreationFailureException( - error_str=str(e)) - return self._make_event_dict(event_db) - - @log.log - def get_event(self, context, event_id, fields=None): - try: - events_db = self._get_by_id(context, Event, event_id) - except orm_exc.NoResultFound: - raise common_services.EventNotFoundException(evt_id=event_id) - return self._make_event_dict(events_db, fields) - - @log.log - def get_events(self, context, filters=None, fields=None, sorts=None, - limit=None, marker_obj=None, page_reverse=False): - return self._get_collection(context, Event, self._make_event_dict, - filters, fields, sorts, limit, - marker_obj, page_reverse) diff --git a/tacker/db/common_services/common_services_db_plugin.py b/tacker/db/common_services/common_services_db_plugin.py new file mode 100644 index 000000000..74af429dc --- /dev/null +++ b/tacker/db/common_services/common_services_db_plugin.py @@ -0,0 +1,88 @@ +# Copyright 2016 Brocade Communications System, 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 sqlalchemy.orm import exc as orm_exc + +from oslo_log import log as logging + +from tacker.common import log +from tacker.db.common_services import common_services_db +from tacker.db import db_base +from tacker.extensions import common_services +from tacker import manager + + +LOG = logging.getLogger(__name__) + +EVENT_ATTRIBUTES = ('id', 'resource_id', 'resource_type', 'resource_state', + 'timestamp', 'event_type', 'event_details') + + +class CommonServicesPluginDb(common_services.CommonServicesPluginBase, + db_base.CommonDbMixin): + + def __init__(self): + super(CommonServicesPluginDb, self).__init__() + + @property + def _core_plugin(self): + return manager.TackerManager.get_plugin() + + def _make_event_dict(self, event_db, fields=None): + res = dict((key, event_db[key]) for key in EVENT_ATTRIBUTES) + return self._fields(res, fields) + + def _fields(self, resource, fields): + if fields: + return dict(((key, item) for key, item in resource.items() + if key in fields)) + return resource + + @log.log + def create_event(self, context, res_id, res_type, res_state, evt_type, + tstamp, details=""): + try: + with context.session.begin(subtransactions=True): + event_db = common_services_db.Event( + resource_id=res_id, + resource_type=res_type, + resource_state=res_state, + event_details=details, + event_type=evt_type, + timestamp=tstamp) + context.session.add(event_db) + except Exception as e: + LOG.exception(_("create event error: %s"), str(e)) + raise common_services.EventCreationFailureException( + error_str=str(e)) + return self._make_event_dict(event_db) + + @log.log + def get_event(self, context, event_id, fields=None): + try: + events_db = self._get_by_id(context, + common_services_db.Event, event_id) + except orm_exc.NoResultFound: + raise common_services.EventNotFoundException(evt_id=event_id) + return self._make_event_dict(events_db, fields) + + @log.log + def get_events(self, context, filters=None, fields=None, sorts=None, + limit=None, marker_obj=None, page_reverse=False): + return self._get_collection(context, common_services_db.Event, + self._make_event_dict, + filters, fields, sorts, limit, + marker_obj, page_reverse) diff --git a/tacker/db/nfvo/nfvo_db.py b/tacker/db/nfvo/nfvo_db.py index 69c7b8b2b..a541aac80 100644 --- a/tacker/db/nfvo/nfvo_db.py +++ b/tacker/db/nfvo/nfvo_db.py @@ -14,33 +14,14 @@ # License for the specific language governing permissions and limitations # under the License. -import uuid - -from oslo_db.exception import DBDuplicateEntry -from oslo_utils import strutils -from oslo_utils import timeutils import sqlalchemy as sa from sqlalchemy import orm -from sqlalchemy.orm import exc as orm_exc from sqlalchemy import schema from sqlalchemy import sql -from tacker.common import exceptions -from tacker.db.common_services import common_services_db -from tacker.db import db_base from tacker.db import model_base from tacker.db import models_v1 from tacker.db import types -from tacker.db.vnfm import vnfm_db -from tacker.extensions import nfvo -from tacker import manager -from tacker.plugins.common import constants - -VIM_ATTRIBUTES = ('id', 'type', 'tenant_id', 'name', 'description', - 'placement_attr', 'shared', 'is_default', - 'created_at', 'updated_at', 'status') - -VIM_AUTH_ATTRIBUTES = ('auth_url', 'vim_project', 'password', 'auth_cred') class Vim(model_base.BASE, @@ -74,172 +55,3 @@ class VimAuth(model_base.BASE, models_v1.HasId): auth_url = sa.Column(sa.String(255), nullable=False) vim_project = sa.Column(types.Json, nullable=False) auth_cred = sa.Column(types.Json, nullable=False) - - -class NfvoPluginDb(nfvo.NFVOPluginBase, db_base.CommonDbMixin): - - def __init__(self): - super(NfvoPluginDb, self).__init__() - self._cos_db_plg = common_services_db.CommonServicesPluginDb() - - @property - def _core_plugin(self): - return manager.TackerManager.get_plugin() - - def _make_vim_dict(self, vim_db, fields=None, mask_password=True): - res = dict((key, vim_db[key]) for key in VIM_ATTRIBUTES) - vim_auth_db = vim_db.vim_auth - res['auth_url'] = vim_auth_db[0].auth_url - res['vim_project'] = vim_auth_db[0].vim_project - res['auth_cred'] = vim_auth_db[0].auth_cred - res['auth_cred']['password'] = vim_auth_db[0].password - if mask_password: - res['auth_cred'] = strutils.mask_dict_password(res['auth_cred']) - return self._fields(res, fields) - - def _fields(self, resource, fields): - if fields: - return dict(((key, item) for key, item in resource.items() - if key in fields)) - return resource - - def _get_resource(self, context, model, id): - try: - return self._get_by_id(context, model, id) - except orm_exc.NoResultFound: - if issubclass(model, Vim): - raise nfvo.VimNotFoundException(vim_id=id) - else: - raise - - def create_vim(self, context, vim): - self._validate_default_vim(context, vim) - vim_cred = vim['auth_cred'] - - try: - with context.session.begin(subtransactions=True): - vim_db = Vim( - id=vim.get('id'), - type=vim.get('type'), - tenant_id=vim.get('tenant_id'), - name=vim.get('name'), - description=vim.get('description'), - placement_attr=vim.get('placement_attr'), - is_default=vim.get('is_default'), - status=vim.get('status')) - context.session.add(vim_db) - vim_auth_db = VimAuth( - id=str(uuid.uuid4()), - vim_id=vim.get('id'), - password=vim_cred.pop('password'), - vim_project=vim.get('vim_project'), - auth_url=vim.get('auth_url'), - auth_cred=vim_cred) - context.session.add(vim_auth_db) - except DBDuplicateEntry as e: - raise exceptions.DuplicateEntity( - _type="vim", - entry=e.columns) - vim_dict = self._make_vim_dict(vim_db) - self._cos_db_plg.create_event( - context, res_id=vim_dict['id'], - res_type=constants.RES_TYPE_VIM, - res_state=vim_dict['status'], - evt_type=constants.RES_EVT_CREATE, - tstamp=vim_dict['created_at']) - return vim_dict - - def delete_vim(self, context, vim_id, soft_delete=True): - with context.session.begin(subtransactions=True): - vim_db = self._get_resource(context, Vim, vim_id) - if soft_delete: - vim_db.update({'deleted_at': timeutils.utcnow()}) - self._cos_db_plg.create_event( - context, res_id=vim_db['id'], - res_type=constants.RES_TYPE_VIM, - res_state=vim_db['status'], - evt_type=constants.RES_EVT_DELETE, - tstamp=vim_db[constants.RES_EVT_DELETED_FLD]) - else: - context.session.query(VimAuth).filter_by( - vim_id=vim_id).delete() - context.session.delete(vim_db) - - def is_vim_still_in_use(self, context, vim_id): - with context.session.begin(subtransactions=True): - vnfs_db = self._model_query(context, vnfm_db.VNF).filter_by( - vim_id=vim_id).first() - if vnfs_db is not None: - raise nfvo.VimInUseException(vim_id=vim_id) - return vnfs_db - - def get_vim(self, context, vim_id, fields=None, mask_password=True): - vim_db = self._get_resource(context, Vim, vim_id) - return self._make_vim_dict(vim_db, mask_password=mask_password) - - def get_vims(self, context, filters=None, fields=None): - return self._get_collection(context, Vim, self._make_vim_dict, - filters=filters, fields=fields) - - def update_vim(self, context, vim_id, vim): - self._validate_default_vim(context, vim, vim_id=vim_id) - with context.session.begin(subtransactions=True): - vim_cred = vim['auth_cred'] - vim_project = vim['vim_project'] - vim_db = self._get_resource(context, Vim, vim_id) - try: - if 'name' in vim: - vim_db.update({'name': vim.get('name')}) - if 'description' in vim: - vim_db.update({'description': vim.get('description')}) - if 'is_default' in vim: - vim_db.update({'is_default': vim.get('is_default')}) - if 'placement_attr' in vim: - vim_db.update( - {'placement_attr': vim.get('placement_attr')}) - vim_auth_db = (self._model_query(context, VimAuth).filter( - VimAuth.vim_id == vim_id).with_lockmode('update').one()) - except orm_exc.NoResultFound: - raise nfvo.VimNotFoundException(vim_id=vim_id) - vim_auth_db.update({'auth_cred': vim_cred, 'password': - vim_cred.pop('password'), 'vim_project': - vim_project}) - vim_db.update({'updated_at': timeutils.utcnow()}) - self._cos_db_plg.create_event( - context, res_id=vim_db['id'], - res_type=constants.RES_TYPE_VIM, - res_state=vim_db['status'], - evt_type=constants.RES_EVT_UPDATE, - tstamp=vim_db[constants.RES_EVT_UPDATED_FLD]) - - return self.get_vim(context, vim_id) - - def update_vim_status(self, context, vim_id, status): - with context.session.begin(subtransactions=True): - try: - vim_db = (self._model_query(context, Vim).filter( - Vim.id == vim_id).with_lockmode('update').one()) - except orm_exc.NoResultFound: - raise nfvo.VimNotFoundException(vim_id=vim_id) - vim_db.update({'status': status, - 'updated_at': timeutils.utcnow()}) - return self._make_vim_dict(vim_db) - - def _validate_default_vim(self, context, vim, vim_id=None): - if not vim.get('is_default'): - return True - try: - vim_db = self._get_default_vim(context) - except orm_exc.NoResultFound: - return True - if vim_id == vim_db.id: - return True - raise nfvo.VimDefaultDuplicateException(vim_id=vim_db.id) - - def _get_default_vim(self, context): - query = self._model_query(context, Vim) - return query.filter(Vim.is_default == sql.true()).one() - - def get_default_vim(self, context): - vim_db = self._get_default_vim(context) - return self._make_vim_dict(vim_db, mask_password=False) diff --git a/tacker/db/nfvo/nfvo_db_plugin.py b/tacker/db/nfvo/nfvo_db_plugin.py new file mode 100644 index 000000000..997536bdd --- /dev/null +++ b/tacker/db/nfvo/nfvo_db_plugin.py @@ -0,0 +1,206 @@ +# 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. + +import uuid + +from oslo_db.exception import DBDuplicateEntry +from oslo_utils import strutils +from oslo_utils import timeutils +from sqlalchemy.orm import exc as orm_exc +from sqlalchemy import sql + +from tacker.common import exceptions +from tacker.db.common_services import common_services_db_plugin +from tacker.db import db_base +from tacker.db.nfvo import nfvo_db +from tacker.db.vnfm import vnfm_db +from tacker.extensions import nfvo +from tacker import manager +from tacker.plugins.common import constants + + +VIM_ATTRIBUTES = ('id', 'type', 'tenant_id', 'name', 'description', + 'placement_attr', 'shared', 'is_default', + 'created_at', 'updated_at', 'status') + +VIM_AUTH_ATTRIBUTES = ('auth_url', 'vim_project', 'password', 'auth_cred') + + +class NfvoPluginDb(nfvo.NFVOPluginBase, db_base.CommonDbMixin): + + def __init__(self): + super(NfvoPluginDb, self).__init__() + self._cos_db_plg = common_services_db_plugin.CommonServicesPluginDb() + + @property + def _core_plugin(self): + return manager.TackerManager.get_plugin() + + def _make_vim_dict(self, vim_db, fields=None, mask_password=True): + res = dict((key, vim_db[key]) for key in VIM_ATTRIBUTES) + vim_auth_db = vim_db.vim_auth + res['auth_url'] = vim_auth_db[0].auth_url + res['vim_project'] = vim_auth_db[0].vim_project + res['auth_cred'] = vim_auth_db[0].auth_cred + res['auth_cred']['password'] = vim_auth_db[0].password + if mask_password: + res['auth_cred'] = strutils.mask_dict_password(res['auth_cred']) + return self._fields(res, fields) + + def _fields(self, resource, fields): + if fields: + return dict(((key, item) for key, item in resource.items() + if key in fields)) + return resource + + def _get_resource(self, context, model, id): + try: + return self._get_by_id(context, model, id) + except orm_exc.NoResultFound: + if issubclass(model, nfvo_db.Vim): + raise nfvo.VimNotFoundException(vim_id=id) + else: + raise + + def create_vim(self, context, vim): + self._validate_default_vim(context, vim) + vim_cred = vim['auth_cred'] + + try: + with context.session.begin(subtransactions=True): + vim_db = nfvo_db.Vim( + id=vim.get('id'), + type=vim.get('type'), + tenant_id=vim.get('tenant_id'), + name=vim.get('name'), + description=vim.get('description'), + placement_attr=vim.get('placement_attr'), + is_default=vim.get('is_default'), + status=vim.get('status')) + context.session.add(vim_db) + vim_auth_db = nfvo_db.VimAuth( + id=str(uuid.uuid4()), + vim_id=vim.get('id'), + password=vim_cred.pop('password'), + vim_project=vim.get('vim_project'), + auth_url=vim.get('auth_url'), + auth_cred=vim_cred) + context.session.add(vim_auth_db) + except DBDuplicateEntry as e: + raise exceptions.DuplicateEntity( + _type="vim", + entry=e.columns) + vim_dict = self._make_vim_dict(vim_db) + self._cos_db_plg.create_event( + context, res_id=vim_dict['id'], + res_type=constants.RES_TYPE_VIM, + res_state=vim_dict['status'], + evt_type=constants.RES_EVT_CREATE, + tstamp=vim_dict['created_at']) + return vim_dict + + def delete_vim(self, context, vim_id, soft_delete=True): + with context.session.begin(subtransactions=True): + vim_db = self._get_resource(context, nfvo_db.Vim, vim_id) + if soft_delete: + vim_db.update({'deleted_at': timeutils.utcnow()}) + self._cos_db_plg.create_event( + context, res_id=vim_db['id'], + res_type=constants.RES_TYPE_VIM, + res_state=vim_db['status'], + evt_type=constants.RES_EVT_DELETE, + tstamp=vim_db[constants.RES_EVT_DELETED_FLD]) + else: + context.session.query(nfvo_db.VimAuth).filter_by( + vim_id=vim_id).delete() + context.session.delete(vim_db) + + def is_vim_still_in_use(self, context, vim_id): + with context.session.begin(subtransactions=True): + vnfs_db = self._model_query(context, vnfm_db.VNF).filter_by( + vim_id=vim_id).first() + if vnfs_db is not None: + raise nfvo.VimInUseException(vim_id=vim_id) + return vnfs_db + + def get_vim(self, context, vim_id, fields=None, mask_password=True): + vim_db = self._get_resource(context, nfvo_db.Vim, vim_id) + return self._make_vim_dict(vim_db, mask_password=mask_password) + + def get_vims(self, context, filters=None, fields=None): + return self._get_collection(context, nfvo_db.Vim, self._make_vim_dict, + filters=filters, fields=fields) + + def update_vim(self, context, vim_id, vim): + self._validate_default_vim(context, vim, vim_id=vim_id) + with context.session.begin(subtransactions=True): + vim_cred = vim['auth_cred'] + vim_project = vim['vim_project'] + vim_db = self._get_resource(context, nfvo_db.Vim, vim_id) + try: + if 'name' in vim: + vim_db.update({'name': vim.get('name')}) + if 'description' in vim: + vim_db.update({'description': vim.get('description')}) + if 'is_default' in vim: + vim_db.update({'is_default': vim.get('is_default')}) + if 'placement_attr' in vim: + vim_db.update( + {'placement_attr': vim.get('placement_attr')}) + vim_auth_db = (self._model_query( + context, nfvo_db.VimAuth).filter( + nfvo_db.VimAuth.vim_id == vim_id).with_lockmode( + 'update').one()) + except orm_exc.NoResultFound: + raise nfvo.VimNotFoundException(vim_id=vim_id) + vim_auth_db.update({'auth_cred': vim_cred, 'password': + vim_cred.pop('password'), 'vim_project': + vim_project}) + vim_db.update({'updated_at': timeutils.utcnow()}) + self._cos_db_plg.create_event( + context, res_id=vim_db['id'], + res_type=constants.RES_TYPE_VIM, + res_state=vim_db['status'], + evt_type=constants.RES_EVT_UPDATE, + tstamp=vim_db[constants.RES_EVT_UPDATED_FLD]) + + return self.get_vim(context, vim_id) + + def update_vim_status(self, context, vim_id, status): + with context.session.begin(subtransactions=True): + try: + vim_db = (self._model_query(context, nfvo_db.Vim).filter( + nfvo_db.Vim.id == vim_id).with_lockmode('update').one()) + except orm_exc.NoResultFound: + raise nfvo.VimNotFoundException(vim_id=vim_id) + vim_db.update({'status': status, + 'updated_at': timeutils.utcnow()}) + return self._make_vim_dict(vim_db) + + def _validate_default_vim(self, context, vim, vim_id=None): + if not vim.get('is_default'): + return True + try: + vim_db = self._get_default_vim(context) + except orm_exc.NoResultFound: + return True + if vim_id == vim_db.id: + return True + raise nfvo.VimDefaultDuplicateException(vim_id=vim_db.id) + + def _get_default_vim(self, context): + query = self._model_query(context, nfvo_db.Vim) + return query.filter(nfvo_db.Vim.is_default == sql.true()).one() + + def get_default_vim(self, context): + vim_db = self._get_default_vim(context) + return self._make_vim_dict(vim_db, mask_password=False) diff --git a/tacker/db/nfvo/ns_db.py b/tacker/db/nfvo/ns_db.py index 89ea89b02..ceb93816d 100644 --- a/tacker/db/nfvo/ns_db.py +++ b/tacker/db/nfvo/ns_db.py @@ -24,7 +24,7 @@ from sqlalchemy.orm import exc as orm_exc from sqlalchemy import schema from tacker.common import exceptions -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.db import db_base from tacker.db import model_base from tacker.db import models_v1 @@ -113,7 +113,7 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin): def __init__(self): super(NSPluginDb, self).__init__() - self._cos_db_plg = common_services_db.CommonServicesPluginDb() + self._cos_db_plg = common_services_db_plugin.CommonServicesPluginDb() def _get_resource(self, context, model, id): try: diff --git a/tacker/db/vnfm/vnfm_db.py b/tacker/db/vnfm/vnfm_db.py index a3a2b01ba..90bc77ca5 100644 --- a/tacker/db/vnfm/vnfm_db.py +++ b/tacker/db/vnfm/vnfm_db.py @@ -29,7 +29,7 @@ from sqlalchemy import schema from tacker.api.v1 import attributes from tacker.common import exceptions from tacker import context as t_context -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.db import db_base from tacker.db import model_base from tacker.db import models_v1 @@ -175,7 +175,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin): def __init__(self): super(VNFMPluginDb, self).__init__() - self._cos_db_plg = common_services_db.CommonServicesPluginDb() + self._cos_db_plg = common_services_db_plugin.CommonServicesPluginDb() def _get_resource(self, context, model, id): try: diff --git a/tacker/nfvo/nfvo_plugin.py b/tacker/nfvo/nfvo_plugin.py index 92c372e25..44ed12c24 100644 --- a/tacker/nfvo/nfvo_plugin.py +++ b/tacker/nfvo/nfvo_plugin.py @@ -33,7 +33,7 @@ from tacker._i18n import _ from tacker.common import driver_manager from tacker.common import log from tacker.common import utils -from tacker.db.nfvo import nfvo_db +from tacker.db.nfvo import nfvo_db_plugin from tacker.db.nfvo import ns_db from tacker.db.nfvo import vnffg_db from tacker.extensions import common_services as cs @@ -56,7 +56,7 @@ def config_opts(): return [('nfvo_vim', NfvoPlugin.OPTS)] -class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin, +class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin, ns_db.NSPluginDb): """NFVO reference plugin for NFVO extension diff --git a/tacker/nfvo/workflows/vim_monitor/vim_ping_action.py b/tacker/nfvo/workflows/vim_monitor/vim_ping_action.py index 000e4f1ad..3dab279f1 100644 --- a/tacker/nfvo/workflows/vim_monitor/vim_ping_action.py +++ b/tacker/nfvo/workflows/vim_monitor/vim_ping_action.py @@ -10,8 +10,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import random - from mistral.actions import base from oslo_config import cfg from oslo_log import log as logging @@ -19,7 +17,8 @@ from oslo_log import log as logging from tacker.agent.linux import utils as linux_utils from tacker.common import rpc from tacker.common import topics - +from tacker.conductor.conductorrpc import vim_monitor_rpc +from tacker import context as t_context LOG = logging.getLogger(__name__) @@ -62,14 +61,14 @@ class PingVimAction(base.Action): return 'UNREACHABLE' def _update(self, status): - # TODO(liuqing) call tacker conductor LOG.info("VIM %s changed to status %s", self.vim_id, status) - x = random.randint(1, 10) - if 0 == (x % 2): - return 'UNREACHABLE' - else: - return 'REACHABLE' - return status + target = vim_monitor_rpc.VIMUpdateRPC.target + rpc_client = rpc.get_client(target) + cctxt = rpc_client.prepare() + return cctxt.call(t_context.get_admin_context_without_session(), + 'update_vim', + vim_id=self.vim_id, + status=status) def run(self): servers = [] diff --git a/tacker/plugins/common_services/common_services_plugin.py b/tacker/plugins/common_services/common_services_plugin.py index f9a3d66e1..12fe1d73d 100644 --- a/tacker/plugins/common_services/common_services_plugin.py +++ b/tacker/plugins/common_services/common_services_plugin.py @@ -15,10 +15,10 @@ # under the License. from tacker.common import log -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin -class CommonServicesPlugin(common_services_db.CommonServicesPluginDb): +class CommonServicesPlugin(common_services_db_plugin.CommonServicesPluginDb): """Reference plugin for COMMONSERVICES extension Implements the COMMONSERVICES extension and defines public facing APIs for diff --git a/tacker/tests/unit/nfvo/test_nfvo_plugin.py b/tacker/tests/unit/nfvo/test_nfvo_plugin.py index 809a43276..4249a92e6 100644 --- a/tacker/tests/unit/nfvo/test_nfvo_plugin.py +++ b/tacker/tests/unit/nfvo/test_nfvo_plugin.py @@ -22,7 +22,7 @@ import uuid from mock import patch from tacker import context -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.db.nfvo import nfvo_db from tacker.db.nfvo import ns_db from tacker.db.nfvo import vnffg_db @@ -200,10 +200,11 @@ class TestNfvoPlugin(db_base.SqlTestCase): mock.patch('tacker.nfvo.nfvo_plugin.NfvoPlugin._get_vim_from_vnf', side_effect=dummy_get_vim).start() self.nfvo_plugin = nfvo_plugin.NfvoPlugin() - mock.patch('tacker.db.common_services.common_services_db.' + mock.patch('tacker.db.common_services.common_services_db_plugin.' 'CommonServicesPluginDb.create_event' ).start() - self._cos_db_plugin = common_services_db.CommonServicesPluginDb() + self._cos_db_plugin =\ + common_services_db_plugin.CommonServicesPluginDb() def _mock_driver_manager(self): self._driver_manager = mock.Mock(wraps=FakeDriverManager()) diff --git a/tacker/tests/unit/test_common_services_plugin.py b/tacker/tests/unit/test_common_services_plugin.py index 3081a15cb..e7488aeae 100644 --- a/tacker/tests/unit/test_common_services_plugin.py +++ b/tacker/tests/unit/test_common_services_plugin.py @@ -18,7 +18,7 @@ import mock from oslo_utils import timeutils from tacker import context -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.extensions import common_services from tacker.plugins.common_services import common_services_plugin from tacker.tests.unit.db import base as db_base @@ -29,7 +29,8 @@ class TestCommonServicesPlugin(db_base.SqlTestCase): super(TestCommonServicesPlugin, self).setUp() self.addCleanup(mock.patch.stopall) self.context = context.get_admin_context() - self.event_db_plugin = common_services_db.CommonServicesPluginDb() + self.event_db_plugin =\ + common_services_db_plugin.CommonServicesPluginDb() self.coreutil_plugin = common_services_plugin.CommonServicesPlugin() def _get_dummy_event_obj(self): diff --git a/tacker/tests/unit/vnfm/test_monitor.py b/tacker/tests/unit/vnfm/test_monitor.py index 060a59e7b..e59622fff 100644 --- a/tacker/tests/unit/vnfm/test_monitor.py +++ b/tacker/tests/unit/vnfm/test_monitor.py @@ -18,7 +18,7 @@ import mock from oslo_utils import timeutils import testtools -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.plugins.common import constants from tacker.vnfm import monitor @@ -56,10 +56,11 @@ class TestVNFMonitor(testtools.TestCase): super(TestVNFMonitor, self).setUp() p = mock.patch('tacker.common.driver_manager.DriverManager') self.mock_monitor_manager = p.start() - mock.patch('tacker.db.common_services.common_services_db.' + mock.patch('tacker.db.common_services.common_services_db_plugin.' 'CommonServicesPluginDb.create_event' ).start() - self._cos_db_plugin = common_services_db.CommonServicesPluginDb() + self._cos_db_plugin =\ + common_services_db_plugin.CommonServicesPluginDb() self.addCleanup(p.stop) def test_to_hosting_vnf(self): diff --git a/tacker/tests/unit/vnfm/test_plugin.py b/tacker/tests/unit/vnfm/test_plugin.py index 7f5a172bd..6e62a9a55 100644 --- a/tacker/tests/unit/vnfm/test_plugin.py +++ b/tacker/tests/unit/vnfm/test_plugin.py @@ -20,7 +20,7 @@ from mock import patch import yaml from tacker import context -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.db.nfvo import nfvo_db from tacker.db.vnfm import vnfm_db from tacker.extensions import vnfm @@ -66,10 +66,11 @@ class TestVNFMPlugin(db_base.SqlTestCase): self._mock_green_pool() self._insert_dummy_vim() self.vnfm_plugin = plugin.VNFMPlugin() - mock.patch('tacker.db.common_services.common_services_db.' + mock.patch('tacker.db.common_services.common_services_db_plugin.' 'CommonServicesPluginDb.create_event' ).start() - self._cos_db_plugin = common_services_db.CommonServicesPluginDb() + self._cos_db_plugin =\ + common_services_db_plugin.CommonServicesPluginDb() def _mock_device_manager(self): self._device_manager = mock.Mock(wraps=FakeDriverManager()) diff --git a/tacker/vnfm/monitor.py b/tacker/vnfm/monitor.py index cb654a6ec..f8f9993de 100644 --- a/tacker/vnfm/monitor.py +++ b/tacker/vnfm/monitor.py @@ -27,7 +27,7 @@ from oslo_utils import timeutils from tacker.common import driver_manager from tacker import context as t_context -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.plugins.common import constants LOG = logging.getLogger(__name__) @@ -47,7 +47,7 @@ def config_opts(): def _log_monitor_events(context, vnf_dict, evt_details): - _cos_db_plg = common_services_db.CommonServicesPluginDb() + _cos_db_plg = common_services_db_plugin.CommonServicesPluginDb() _cos_db_plg.create_event(context, res_id=vnf_dict['id'], res_type=constants.RES_TYPE_VNF, res_state=vnf_dict['status'], diff --git a/tacker/vnfm/policy_actions/autoscaling/autoscaling.py b/tacker/vnfm/policy_actions/autoscaling/autoscaling.py index c81d7edde..acf078a4b 100644 --- a/tacker/vnfm/policy_actions/autoscaling/autoscaling.py +++ b/tacker/vnfm/policy_actions/autoscaling/autoscaling.py @@ -15,7 +15,7 @@ from oslo_log import log as logging from oslo_utils import timeutils -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.plugins.common import constants from tacker.vnfm.policy_actions import abstract_action @@ -23,7 +23,7 @@ LOG = logging.getLogger(__name__) def _log_monitor_events(context, vnf_dict, evt_details): - _cos_db_plg = common_services_db.CommonServicesPluginDb() + _cos_db_plg = common_services_db_plugin.CommonServicesPluginDb() _cos_db_plg.create_event(context, res_id=vnf_dict['id'], res_type=constants.RES_TYPE_VNF, res_state=vnf_dict['status'], diff --git a/tacker/vnfm/policy_actions/log/log.py b/tacker/vnfm/policy_actions/log/log.py index 9fce410ea..5d0357e43 100644 --- a/tacker/vnfm/policy_actions/log/log.py +++ b/tacker/vnfm/policy_actions/log/log.py @@ -15,7 +15,7 @@ from oslo_log import log as logging from oslo_utils import timeutils -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.plugins.common import constants from tacker.vnfm.policy_actions import abstract_action @@ -23,7 +23,7 @@ LOG = logging.getLogger(__name__) def _log_monitor_events(context, vnf_dict, evt_details): - _cos_db_plg = common_services_db.CommonServicesPluginDb() + _cos_db_plg = common_services_db_plugin.CommonServicesPluginDb() _cos_db_plg.create_event(context, res_id=vnf_dict['id'], res_type=constants.RES_TYPE_VNF, res_state=vnf_dict['status'], diff --git a/tacker/vnfm/policy_actions/respawn/respawn.py b/tacker/vnfm/policy_actions/respawn/respawn.py index e315164f9..9b8c2fe57 100644 --- a/tacker/vnfm/policy_actions/respawn/respawn.py +++ b/tacker/vnfm/policy_actions/respawn/respawn.py @@ -15,7 +15,7 @@ from oslo_log import log as logging from oslo_utils import timeutils -from tacker.db.common_services import common_services_db +from tacker.db.common_services import common_services_db_plugin from tacker.plugins.common import constants from tacker.vnfm.infra_drivers.openstack import heat_client as hc from tacker.vnfm.policy_actions import abstract_action @@ -25,7 +25,7 @@ LOG = logging.getLogger(__name__) def _log_monitor_events(context, vnf_dict, evt_details): - _cos_db_plg = common_services_db.CommonServicesPluginDb() + _cos_db_plg = common_services_db_plugin.CommonServicesPluginDb() _cos_db_plg.create_event(context, res_id=vnf_dict['id'], res_type=constants.RES_TYPE_VNF, res_state=vnf_dict['status'],