Implement vim status update in conductor
Mistral vim monitor task connects to conductor via conductor's AMQP topic, calls the update_vim RPC method. The RPC method will update vim and event DB entries and then return passed in status. This patch refactors the common_services_db and nfvo_db in order not to import too many classes in the conductor process. One more thing is on devstack, where tacker-conductor service is introduced. DocImpact Implements: blueprint refactor-vim-monitor Change-Id: Ic2b3c381cca796edc00f3c77cc790cb4c4955db7
This commit is contained in:
parent
60187643b5
commit
755a55ad5f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -12,3 +12,4 @@
|
||||
|
||||
|
||||
TOPIC_ACTION_KILL = 'KILL_ACTION'
|
||||
TOPIC_CONDUCTOR = 'TACKER_CONDUCTOR'
|
||||
|
@ -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()
|
||||
|
@ -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
|
@ -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)
|
||||
|
88
tacker/db/common_services/common_services_db_plugin.py
Normal file
88
tacker/db/common_services/common_services_db_plugin.py
Normal file
@ -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)
|
@ -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)
|
||||
|
206
tacker/db/nfvo/nfvo_db_plugin.py
Normal file
206
tacker/db/nfvo/nfvo_db_plugin.py
Normal file
@ -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)
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = []
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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())
|
||||
|
@ -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'],
|
||||
|
@ -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'],
|
||||
|
@ -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'],
|
||||
|
@ -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'],
|
||||
|
Loading…
Reference in New Issue
Block a user