Add monitor feature to the VIM
This patch add monitoring feature to the VIM by checking the reachability of identity service for the corresponding VIM. Change-Id: I25beaa5e1fd2fca87503c45d720f89d6f8156622 Closes-Bug: #1554280
This commit is contained in:
parent
daa7bf4e8e
commit
792b1e0183
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Add VIM health monitor to Tacker
|
@ -0,0 +1,35 @@
|
||||
# Copyright 2016 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Add status to vims
|
||||
|
||||
Revision ID: 22f5385a3d3f
|
||||
Revises: 5246a6bd410f
|
||||
Create Date: 2016-05-12 13:29:30.615609
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '22f5385a3d3f'
|
||||
down_revision = '5f88e86b35c7'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
op.add_column('vims',
|
||||
sa.Column('status', sa.String(255),
|
||||
nullable=False, server_default=''))
|
@ -1 +1 @@
|
||||
5f88e86b35c7
|
||||
22f5385a3d3f
|
||||
|
@ -33,7 +33,7 @@ from tacker import manager
|
||||
|
||||
|
||||
VIM_ATTRIBUTES = ('id', 'type', 'tenant_id', 'name', 'description',
|
||||
'placement_attr', 'shared')
|
||||
'placement_attr', 'shared', 'status')
|
||||
VIM_AUTH_ATTRIBUTES = ('auth_url', 'vim_project', 'password', 'auth_cred')
|
||||
|
||||
|
||||
@ -45,6 +45,7 @@ class Vim(model_base.BASE, models_v1.HasId, models_v1.HasTenant):
|
||||
shared = sa.Column(sa.Boolean, default=True, server_default=sql.true(
|
||||
), nullable=False)
|
||||
vim_auth = orm.relationship('VimAuth')
|
||||
status = sa.Column(sa.String(255), nullable=False)
|
||||
|
||||
|
||||
class VimAuth(model_base.BASE, models_v1.HasId):
|
||||
@ -102,7 +103,8 @@ class NfvoPluginDb(nfvo.NFVOPluginBase, db_base.CommonDbMixin):
|
||||
tenant_id=vim.get('tenant_id'),
|
||||
name=vim.get('name'),
|
||||
description=vim.get('description'),
|
||||
placement_attr=vim.get('placement_attr'))
|
||||
placement_attr=vim.get('placement_attr'),
|
||||
status=vim.get('status'))
|
||||
context.session.add(vim_db)
|
||||
vim_auth_db = VimAuth(
|
||||
id=str(uuid.uuid4()),
|
||||
@ -153,6 +155,16 @@ class NfvoPluginDb(nfvo.NFVOPluginBase, db_base.CommonDbMixin):
|
||||
vim_project})
|
||||
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})
|
||||
return self._make_vim_dict(vim_db)
|
||||
|
||||
def get_vim_by_name(self, context, vim_name, fields=None,
|
||||
mask_password=True):
|
||||
vim_db = self._get_by_name(context, Vim, vim_name)
|
||||
|
@ -120,6 +120,12 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'is_visible': True,
|
||||
'default': '',
|
||||
},
|
||||
'status': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'validate': {'type:string': None},
|
||||
'is_visible': True,
|
||||
},
|
||||
'placement_attr': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
|
@ -82,3 +82,11 @@ class VimAbstractDriver(extensions.PluginInterface):
|
||||
Delete VIM sensitive information such as keys from file system or DB
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def vim_status(self, auth_url):
|
||||
"""Health check for VIM
|
||||
|
||||
Checks the health status of VIM and return a boolean value
|
||||
"""
|
||||
pass
|
||||
|
@ -20,8 +20,10 @@ from keystoneclient import exceptions
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from tacker.agent.linux import utils as linux_utils
|
||||
from tacker.common import log
|
||||
from tacker.extensions import nfvo
|
||||
from tacker.i18n import _LW
|
||||
from tacker.nfvo.drivers.vim import abstract_vim_driver
|
||||
from tacker.vm import keystone
|
||||
|
||||
@ -31,7 +33,18 @@ CONF = cfg.CONF
|
||||
|
||||
OPTS = [cfg.StrOpt('openstack', default='/etc/tacker/vim/fernet_keys',
|
||||
help='Dir.path to store fernet keys.')]
|
||||
|
||||
# same params as we used in ping monitor driver
|
||||
OPENSTACK_OPTS = [
|
||||
cfg.StrOpt('count', default='1',
|
||||
help=_('number of ICMP packets to send')),
|
||||
cfg.StrOpt('timeout', default='1',
|
||||
help=_('number of seconds to wait for a response')),
|
||||
cfg.StrOpt('interval', default='1',
|
||||
help=_('number of seconds to wait between packets'))
|
||||
]
|
||||
cfg.CONF.register_opts(OPTS, 'vim_keys')
|
||||
cfg.CONF.register_opts(OPENSTACK_OPTS, 'vim_monitor')
|
||||
|
||||
|
||||
class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver):
|
||||
@ -178,3 +191,20 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver):
|
||||
LOG.debug(_('VIM auth successfully stored for vim %s'), vim_id)
|
||||
except IOError:
|
||||
raise nfvo.VimKeyNotFoundException(vim_id=vim_id)
|
||||
|
||||
@log.log
|
||||
def vim_status(self, auth_url):
|
||||
"""Checks the VIM health status"""
|
||||
vim_ip = auth_url.split("//")[-1].split(":")[0].split("/")[0]
|
||||
ping_cmd = ['ping',
|
||||
'-c', cfg.CONF.vim_monitor.count,
|
||||
'-W', cfg.CONF.vim_monitor.timeout,
|
||||
'-i', cfg.CONF.vim_monitor.interval,
|
||||
vim_ip]
|
||||
|
||||
try:
|
||||
linux_utils.execute(ping_cmd, check_exit_code=True)
|
||||
return True
|
||||
except RuntimeError:
|
||||
LOG.warning(_LW("Cannot ping ip address: %s"), vim_ip)
|
||||
return False
|
||||
|
@ -14,6 +14,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import threading
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
@ -23,6 +25,7 @@ from oslo_utils import excutils
|
||||
from tacker.common import driver_manager
|
||||
from tacker.common import log
|
||||
from tacker.common import utils
|
||||
from tacker import context as t_context
|
||||
from tacker.db.nfvo import nfvo_db
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -37,11 +40,15 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb):
|
||||
extension for providing the specified VIM information
|
||||
"""
|
||||
supported_extension_aliases = ['nfvo']
|
||||
_lock = threading.RLock()
|
||||
|
||||
OPTS = [
|
||||
cfg.ListOpt(
|
||||
'vim_drivers', default=['openstack'],
|
||||
help=_('VIM driver for launching VNFs')),
|
||||
cfg.IntOpt(
|
||||
'monitor_interval', default=30,
|
||||
help=_('Interval to check for VIM health')),
|
||||
]
|
||||
cfg.CONF.register_opts(OPTS, 'nfvo_vim')
|
||||
|
||||
@ -50,6 +57,19 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb):
|
||||
self._vim_drivers = driver_manager.DriverManager(
|
||||
'tacker.nfvo.vim.drivers',
|
||||
cfg.CONF.nfvo_vim.vim_drivers)
|
||||
self._created_vims = dict()
|
||||
context = t_context.get_admin_context()
|
||||
vims = self.get_vims(context)
|
||||
for vim in vims:
|
||||
self._created_vims[vim["id"]] = vim
|
||||
self._monitor_interval = cfg.CONF.nfvo_vim.monitor_interval
|
||||
threading.Thread(target=self.__run__).start()
|
||||
|
||||
def __run__(self):
|
||||
while(1):
|
||||
time.sleep(self._monitor_interval)
|
||||
for created_vim in self._created_vims.values():
|
||||
self.monitor_vim(created_vim)
|
||||
|
||||
@log.log
|
||||
def create_vim(self, context, vim):
|
||||
@ -57,9 +77,14 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb):
|
||||
vim_obj = vim['vim']
|
||||
vim_type = vim_obj['type']
|
||||
vim_obj['id'] = str(uuid.uuid4())
|
||||
vim_obj['status'] = 'PENDING'
|
||||
try:
|
||||
self._vim_drivers.invoke(vim_type, 'register_vim', vim_obj=vim_obj)
|
||||
res = super(NfvoPlugin, self).create_vim(context, vim_obj)
|
||||
vim_obj["status"] = "REGISTERING"
|
||||
with self._lock:
|
||||
self._created_vims[res["id"]] = res
|
||||
self.monitor_vim(vim_obj)
|
||||
return res
|
||||
except Exception:
|
||||
with excutils.save_and_reraise_exception():
|
||||
@ -88,4 +113,22 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb):
|
||||
vim_obj = self._get_vim(context, vim_id)
|
||||
self._vim_drivers.invoke(vim_obj['type'], 'deregister_vim',
|
||||
vim_id=vim_id)
|
||||
with self._lock:
|
||||
self._created_vims.pop(vim_id, None)
|
||||
super(NfvoPlugin, self).delete_vim(context, vim_id)
|
||||
|
||||
@log.log
|
||||
def monitor_vim(self, vim_obj):
|
||||
vim_id = vim_obj["id"]
|
||||
auth_url = vim_obj["auth_url"]
|
||||
vim_status = self._vim_drivers.invoke(vim_obj['type'],
|
||||
'vim_status',
|
||||
auth_url=auth_url)
|
||||
current_status = "REACHABLE" if vim_status else "UNREACHABLE"
|
||||
if current_status != vim_obj["status"]:
|
||||
status = current_status
|
||||
with self._lock:
|
||||
super(NfvoPlugin, self).update_vim_status(
|
||||
t_context.get_admin_context(),
|
||||
vim_id, status)
|
||||
self._created_vims[vim_id]["status"] = status
|
||||
|
@ -37,6 +37,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
self.context = context.get_admin_context()
|
||||
self._mock_driver_manager()
|
||||
mock.patch('tacker.nfvo.nfvo_plugin.NfvoPlugin.__run__').start()
|
||||
self.nfvo_plugin = nfvo_plugin.NfvoPlugin()
|
||||
|
||||
def _mock_driver_manager(self):
|
||||
@ -56,6 +57,7 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
name='fake_vim',
|
||||
description='fake_vim_description',
|
||||
type='openstack',
|
||||
status='Active',
|
||||
placement_attr={'regions': ['RegionOne']})
|
||||
vim_auth_db = nfvo_db.VimAuth(
|
||||
vim_id='6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
@ -78,10 +80,10 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
'tenant_id': 'test-project'}}
|
||||
vim_type = 'openstack'
|
||||
res = self.nfvo_plugin.create_vim(self.context, vim_dict)
|
||||
self._driver_manager.invoke.assert_called_once_with(vim_type,
|
||||
'register_vim',
|
||||
vim_obj=vim_dict[
|
||||
'vim'])
|
||||
self._driver_manager.invoke.assert_any_call(vim_type,
|
||||
'register_vim', vim_obj=vim_dict['vim'])
|
||||
self._driver_manager.invoke.assert_any_call('openstack', 'vim_status',
|
||||
auth_url='http://localhost:5000')
|
||||
self.assertIsNotNone(res)
|
||||
self.assertEqual(SECRET_PASSWORD, res['auth_cred']['password'])
|
||||
self.assertIn('id', res)
|
||||
|
@ -132,6 +132,7 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
||||
name='fake_vim',
|
||||
description='fake_vim_description',
|
||||
type='openstack',
|
||||
status='Active',
|
||||
placement_attr={'regions': ['RegionOne']})
|
||||
vim_auth_db = nfvo_db.VimAuth(
|
||||
vim_id='6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
|
Loading…
Reference in New Issue
Block a user