Merge "Derive infra driver using VIM type"

This commit is contained in:
Jenkins 2016-09-16 14:22:05 +00:00 committed by Gerrit Code Review
commit 2f98f410d9
17 changed files with 260 additions and 212 deletions

View File

@ -58,7 +58,7 @@ List vnfds - List vnfds stored in the VNF catalog.
"description": "OpenWRT with services",
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
"mgmt_driver": "openwrt",
"infra_driver": "heat",
"infra_driver": "",
"attributes": {
"vnfd": "template_name: OpenWRT\r\ndescription:
template_description <sample_vnfd_template>"
@ -87,7 +87,7 @@ Show vnfd - Show information for a specified vnfd id.
"description": "OpenWRT with services",
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
"mgmt_driver": "openwrt",
"infra_driver": "heat",
"infra_driver": "",
"attributes": {
"vnfd": "template_name: OpenWRT\r\ndescription:
template_description <sample_vnfd_template>"
@ -116,8 +116,6 @@ Create vnfd - Create a vnfd entry based on the vnfd template.
"service_types": [{"service_type": "vnfd"}],
"tenant_id": "bb6a3be1021a4746ab727a6c9296e797",
"description": "OpenWRT router",
"mgmt_driver": "noop",
"infra_driver": "heat",
"attributes": {
"vnfd": "template_name: sample-vnfd\ndescription: demo-example\n\nservice_properties:\n Id: sample-vnfd\n vendor: tacker\n version: 1\n\nvdus:\n vdu1:\n id: vdu1\n vm_image: cirros-0.3.4-x86_64-uec\n instance_type: m1.tiny\n\n network_interfaces:\n management:\n network: net_mgmt\n management: true\n pkt_in:\n network: net0\n pkt_out:\n network: net1\n\n placement_policy:\n availability_zone: nova\n\n auto-scaling: noop\n\n config:\n param0: key0\n param1: key1\n"
},
@ -139,7 +137,7 @@ Create vnfd - Create a vnfd entry based on the vnfd template.
"description": "OpenWRT router",
"tenant_id": "4dd6c1d7b6c94af980ca886495bcfed0",
"mgmt_driver": "noop",
"infra_driver": "heat",
"infra_driver": "",
"attributes": {
"vnfd": "template_name: OpenWRT \r\ndescription:
template_description <sample_vnfd_template>"

View File

@ -10,6 +10,7 @@ namespace = tacker.vnfm.monitor
namespace = tacker.vnfm.plugin
namespace = tacker.vnfm.vim_client
namespace = tacker.vnfm.infra_drivers.heat.heat
namespace = tacker.vnfm.infra_drivers.openstack.openstack
namespace = tacker.vnfm.mgmt_drivers.openwrt.openwrt
namespace = tacker.vnfm.monitor_drivers.http_ping.http_ping
namespace = tacker.vnfm.monitor_drivers.ping.ping

View File

@ -50,7 +50,8 @@ tacker.openstack.common.cache.backends =
tacker.tacker.device.drivers =
noop = tacker.vnfm.infra_drivers.noop:DeviceNoop
nova = tacker.vnfm.infra_drivers.nova.nova:DeviceNova
heat = tacker.vnfm.infra_drivers.heat.heat:DeviceHeat
heat = tacker.vnfm.infra_drivers.vim_heat.vim_heat:VimHeat
openstack = tacker.vnfm.infra_drivers.openstack.openstack:OpenStack
tacker.tacker.mgmt.drivers =
noop = tacker.vnfm.mgmt_drivers.noop:DeviceMgmtNoop
openwrt = tacker.vnfm.mgmt_drivers.openwrt.openwrt:DeviceMgmtOpenWRT
@ -66,7 +67,8 @@ oslo.config.opts =
tacker.vnfm.monitor = tacker.vnfm.monitor:config_opts
tacker.vnfm.plugin = tacker.vm.plugin:config_opts
tacker.vnfm.vim_client = tacker.vnfm.vim_client:config_opts
tacker.vnfm.infra_drivers.heat.heat= tacker.vnfm.infra_drivers.heat.heat:config_opts
tacker.vnfm.infra_drivers.heat.heat= tacker.vnfm.infra_drivers.vim_heat.vim_heat:config_opts
tacker.vnfm.infra_drivers.openstack.openstack= tacker.vnfm.infra_drivers.openstack.openstack:config_opts
tacker.vnfm.mgmt_drivers.openwrt.openwrt = tacker.vnfm.mgmt_drivers.openwrt.openwrt:config_opts
tacker.vnfm.monitor_drivers.http_ping.http_ping = tacker.vnfm.monitor_drivers.http_ping.http_ping:config_opts
tacker.vnfm.monitor_drivers.ping.ping = tacker.vnfm.monitor_drivers.ping.ping:config_opts

View File

@ -17,7 +17,6 @@
import uuid
from oslo_log import log as logging
from oslo_log import versionutils
from oslo_utils import timeutils
import sqlalchemy as sa
@ -230,19 +229,6 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
mgmt_driver = vnfd.get('mgmt_driver')
service_types = vnfd.get('service_types')
if 'infra_driver' in vnfd or 'mgmt_driver' in vnfd:
versionutils.report_deprecated_feature(LOG, "Deriving "
"infra_driver and mgmt_driver from VNFD API is deprecated and"
" will be removed in Ocata. infra_driver will be automatically"
" derived from target vim type. mgmt_driver will be derived "
"from TOSCA template values.")
if (not attributes.is_attr_set(infra_driver)):
LOG.debug(_('hosting vnf driver unspecified'))
raise vnfm.InfraDriverNotSpecified()
if (not attributes.is_attr_set(mgmt_driver)):
LOG.debug(_('mgmt driver unspecified'))
raise vnfm.MGMTDriverNotSpecified()
if (not attributes.is_attr_set(service_types)):
LOG.debug(_('service types unspecified'))
raise vnfm.ServiceTypesNotSpecified()

View File

@ -56,7 +56,7 @@ class VNFInUse(exceptions.InUse):
class InvalidInfraDriver(exceptions.InvalidInput):
message = _('invalid name for infra driver %(infra_driver)s')
message = _('VIM type %(vim_name)s is not supported as a infra driver ')
class InvalidServiceType(exceptions.InvalidInput):
@ -220,14 +220,14 @@ RESOURCE_ATTRIBUTE_MAP = {
'allow_put': False,
'validate': {'type:string': None},
'is_visible': True,
'default': attr.ATTR_NOT_SPECIFIED,
'default': "",
},
'mgmt_driver': {
'allow_post': True,
'allow_put': False,
'validate': {'type:string': None},
'is_visible': True,
'default': attr.ATTR_NOT_SPECIFIED,
'default': "",
},
'attributes': {
'allow_post': True,

View File

@ -25,7 +25,7 @@ def _get_template(name):
f = codecs.open(filename, encoding='utf-8', errors='strict')
return f.read()
vnfd_openwrt = _get_template('openwrt.yaml')
vnfd_openwrt = _get_template('test_tosca_openwrt.yaml')
vnfd_ipparams_template = _get_template('vnf_cirros_template_ipaddr.yaml')
ipparams = _get_template('vnf_cirros_param_values_ipaddr.yaml')
vnfd_userdata_template = _get_template('vnf_cirros_template_user_data.yaml')
@ -42,7 +42,6 @@ def get_dummy_vnfd_obj():
'name': 'dummy_vnfd',
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
u'mgmt_driver': u'noop',
u'infra_driver': u'fake_driver',
u'attributes': {u'vnfd': yaml.safe_load(vnfd_openwrt)},
'description': 'dummy_vnfd_description'},
u'auth': {u'tenantName': u'admin', u'passwordCredentials': {
@ -73,7 +72,6 @@ def get_dummy_device_obj():
'description': u'OpenWRT with services',
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
'mgmt_driver': u'openwrt',
'infra_driver': u'heat',
'attributes': {u'vnfd': vnfd_openwrt},
'id': u'fb048660-dc1b-4f0f-bd89-b023666650ec',
'name': u'openwrt_services'},
@ -92,7 +90,6 @@ def get_dummy_device_obj_config_attr():
'description': u'OpenWRT with services',
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
'mgmt_driver': u'openwrt',
'infra_driver': u'heat',
'attributes': {u'vnfd': vnfd_openwrt},
'id': u'fb048660-dc1b-4f0f-bd89-b023666650ec', 'name':
u'openwrt_services'}, 'mgmt_url': None, 'service_context': [],
@ -126,7 +123,6 @@ def get_dummy_device_obj_ipaddr_attr():
'description': u'Parameterized VNF descriptor for IP addresses',
'tenant_id': u'4dd6c1d7b6c94af980ca886495bcfed0',
'mgmt_driver': u'noop',
'infra_driver': u'heat',
'attributes': {u'vnfd': vnfd_ipparams_template},
'id': u'24c31ea1-2e28-4de2-a6cb-8d389a502c75', 'name': u'ip_vnfd'},
'name': u'test_ip',
@ -152,7 +148,6 @@ def get_dummy_device_obj_userdata_attr():
'description': u"Parameterized VNF descriptor",
'tenant_id': u'8273659b56fc46b68bd05856d1f08d14',
'mgmt_driver': u'noop',
'infra_driver': u'heat',
'attributes': {u'vnfd': vnfd_userdata_template},
'id': u'206e343f-c580-4494-a739-525849edab7f', 'name':
u'cirros_user_data'}, 'mgmt_url': None, 'service_context': [],

View File

@ -23,7 +23,7 @@ from tacker import context
from tacker.extensions import vnfm
from tacker.tests.unit import base
from tacker.tests.unit.db import utils
from tacker.vnfm.infra_drivers.heat import heat
from tacker.vnfm.infra_drivers.openstack import openstack
class FakeHeatClient(mock.Mock):
@ -47,17 +47,17 @@ def _get_template(name):
return f.read()
class TestDeviceHeat(base.TestCase):
hot_template = _get_template('hot_openwrt.yaml')
class TestOpenStack(base.TestCase):
hot_template = _get_template('hot_tosca_openwrt.yaml')
hot_param_template = _get_template('hot_openwrt_params.yaml')
hot_ipparam_template = _get_template('hot_openwrt_ipparams.yaml')
vnfd_openwrt = _get_template('openwrt.yaml')
vnfd_openwrt = _get_template('test_tosca_openwrt.yaml')
config_data = _get_template('config_data.yaml')
def setUp(self):
super(TestDeviceHeat, self).setUp()
super(TestOpenStack, self).setUp()
self.context = context.get_admin_context()
self.heat_driver = heat.DeviceHeat()
self.infra_driver = openstack.OpenStack()
self._mock_heat_client()
self.addCleanup(mock.patch.stopall)
@ -66,7 +66,8 @@ class TestDeviceHeat(base.TestCase):
fake_heat_client = mock.Mock()
fake_heat_client.return_value = self.heat_client
self._mock(
'tacker.vnfm.infra_drivers.heat.heat.HeatClient', fake_heat_client)
'tacker.vnfm.infra_drivers.openstack.openstack.HeatClient',
fake_heat_client)
def _mock(self, target, new=mock.DEFAULT):
patcher = mock.patch(target, new)
@ -83,19 +84,20 @@ class TestDeviceHeat(base.TestCase):
def _get_expected_fields(self):
return {'stack_name':
'tacker.vnfm.infra_drivers.heat.heat_DeviceHeat-eb84260e'
'-5ff7-4332-b032-50a14d6c1123', 'template': self.hot_template}
'tacker.vnfm.infra_drivers.openstack.openstack_OpenStack'
'-eb84260e-5ff7-4332-b032-50a14d6c1123', 'template':
self.hot_template}
def _get_expected_fields_user_data(self):
return {'stack_name':
'tacker.vnfm.infra_drivers.heat.heat_DeviceHeat-18685f68'
'-2b2a-4185-8566-74f54e548811',
'tacker.vnfm.infra_drivers.openstack.openstack_OpenStack'
'-18685f68-2b2a-4185-8566-74f54e548811',
'template': self.hot_param_template}
def _get_expected_fields_ipaddr_data(self):
return {'stack_name':
'tacker.vnfm.infra_drivers.heat.heat_DeviceHeat-d1337add'
'-d5a1-4fd4-9447-bb9243c8460b',
'tacker.vnfm.infra_drivers.openstack.openstack_OpenStack'
'-d1337add-d5a1-4fd4-9447-bb9243c8460b',
'template': self.hot_ipparam_template}
def _get_expected_vnf_wait_obj(self, param_values=''):
@ -111,7 +113,6 @@ class TestDeviceHeat(base.TestCase):
'description': u'OpenWRT with services',
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
'mgmt_driver': u'openwrt',
'infra_driver': u'heat',
'attributes': {u'vnfd': self.vnfd_openwrt},
'id': u'fb048660-dc1b-4f0f-bd89-b023666650ec',
'name': u'openwrt_services'},
@ -130,7 +131,6 @@ class TestDeviceHeat(base.TestCase):
u'4a4c2d44-8a52-4895-9a75-9d1c76c3e738'}], 'description':
u'OpenWRT with services', 'tenant_id':
u'ad7ebc56538745a08ef7c5e97f8bd437', 'mgmt_driver': u'openwrt',
'infra_driver': u'heat',
'attributes': {u'vnfd': self.vnfd_openwrt},
'id': u'fb048660-dc1b-4f0f-bd89-b023666650ec', 'name':
u'openwrt_services'}, 'mgmt_url': None, 'service_context': [],
@ -170,7 +170,7 @@ class TestDeviceHeat(base.TestCase):
vnf_obj = utils.get_dummy_device_obj()
expected_result = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738'
expected_fields = self._get_expected_fields()
result = self.heat_driver.create(plugin=None, context=self.context,
result = self.infra_driver.create(plugin=None, context=self.context,
vnf=vnf_obj,
auth_attr=utils.get_vim_auth_obj())
self.heat_client.create.assert_called_once_with(expected_fields)
@ -180,7 +180,7 @@ class TestDeviceHeat(base.TestCase):
vnf_obj = utils.get_dummy_device_obj_userdata_attr()
expected_result = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738'
expected_fields = self._get_expected_fields_user_data()
result = self.heat_driver.create(plugin=None, context=self.context,
result = self.infra_driver.create(plugin=None, context=self.context,
vnf=vnf_obj,
auth_attr=utils.get_vim_auth_obj())
self.heat_client.create.assert_called_once_with(expected_fields)
@ -190,7 +190,7 @@ class TestDeviceHeat(base.TestCase):
vnf_obj = utils.get_dummy_device_obj_ipaddr_attr()
expected_result = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738'
expected_fields = self._get_expected_fields_ipaddr_data()
result = self.heat_driver.create(plugin=None, context=self.context,
result = self.infra_driver.create(plugin=None, context=self.context,
vnf=vnf_obj,
auth_attr=utils.get_vim_auth_obj())
self.heat_client.create.assert_called_once_with(expected_fields)
@ -200,7 +200,7 @@ class TestDeviceHeat(base.TestCase):
vnf_obj = utils.get_dummy_device_obj()
expected_result = self._get_expected_vnf_wait_obj()
vnf_id = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738'
self.heat_driver.create_wait(plugin=None,
self.infra_driver.create_wait(plugin=None,
context=self.context,
vnf_dict=vnf_obj,
vnf_id=vnf_id,
@ -209,7 +209,7 @@ class TestDeviceHeat(base.TestCase):
def test_delete(self):
vnf_id = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738'
self.heat_driver.delete(plugin=None, context=self.context,
self.infra_driver.delete(plugin=None, context=self.context,
vnf_id=vnf_id,
auth_attr=utils.get_vim_auth_obj())
self.heat_client.delete.assert_called_once_with(vnf_id)
@ -219,22 +219,16 @@ class TestDeviceHeat(base.TestCase):
vnf_config_obj = utils.get_dummy_device_update_config_attr()
expected_vnf_update = self._get_expected_vnf_update_obj()
vnf_id = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738'
self.heat_driver.update(plugin=None, context=self.context,
self.infra_driver.update(plugin=None, context=self.context,
vnf_id=vnf_id, vnf_dict=vnf_obj,
vnf=vnf_config_obj,
auth_attr=utils.get_vim_auth_obj())
self.assertEqual(expected_vnf_update, vnf_obj)
def test_create_vnfd_pre_tosca(self):
tosca_tpl = _get_template('test_tosca_openwrt.yaml')
dtemplate = self._get_vnfd(tosca_tpl)
exp_tmpl = self._get_expected_vnfd(tosca_tpl)
self.heat_driver.create_vnfd_pre(None, None, dtemplate)
self.assertEqual(exp_tmpl, dtemplate)
def _get_expected_fields_tosca(self, template):
return {'stack_name':
'tacker.vnfm.infra_drivers.heat.heat_DeviceHeat-eb84260e'
'tacker.vnfm.infra_drivers.openstack.openstack_OpenStack'
'-eb84260e'
'-5ff7-4332-b032-50a14d6c1123',
'template': _get_template(template)}
@ -299,7 +293,7 @@ class TestDeviceHeat(base.TestCase):
hot_tpl_name,
input_params,
is_monitor)
result = self.heat_driver.create(plugin=None, context=self.context,
result = self.infra_driver.create(plugin=None, context=self.context,
vnf=vnf,
auth_attr=utils.get_vim_auth_obj())
actual_fields = self.heat_client.create.call_args[0][0]
@ -436,7 +430,7 @@ class TestDeviceHeat(base.TestCase):
vnf_obj = self._get_expected_active_vnf()
print(vnf_obj)
self.assertRaises(vnfm.InfraDriverUnreachable,
self.heat_driver.get_resource_info,
self.infra_driver.get_resource_info,
plugin=None, context=self.context, vnf_info=vnf_obj,
auth_attr=utils.get_vim_auth_obj(),
region_name=None)

View File

@ -16,6 +16,7 @@
import uuid
import mock
import yaml
from tacker import context
from tacker.db.common_services import common_services_db
@ -88,7 +89,7 @@ class TestVNFMPlugin(db_base.SqlTestCase):
'vim_name': 'fake_vim', 'vim_auth':
{'auth_url': 'http://localhost:5000', 'password':
'test_pw', 'username': 'test_user', 'project_name':
'test_project'}}
'test_project'}, 'vim_type': 'test_vim'}
self.vim_client.get_vim.return_value = vim_obj
def _mock_green_pool(self):
@ -141,7 +142,7 @@ class TestVNFMPlugin(db_base.SqlTestCase):
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
name='fake_vim',
description='fake_vim_description',
type='openstack',
type='test_vim',
status='Active',
placement_attr={'regions': ['RegionOne']})
vim_auth_db = nfvo_db.VimAuth(
@ -155,21 +156,30 @@ class TestVNFMPlugin(db_base.SqlTestCase):
session.add(vim_auth_db)
session.flush()
def test_create_vnfd(self):
@mock.patch('tacker.vm.plugin.toscautils.updateimports')
@mock.patch('tacker.vm.plugin.ToscaTemplate')
@mock.patch('tacker.vm.plugin.toscautils.get_mgmt_driver')
def test_create_vnfd(self, mock_get_mgmt_driver, mock_tosca_template,
mock_update_imports):
mock_get_mgmt_driver.return_value = 'dummy_mgmt_driver'
mock_tosca_template.return_value = mock.ANY
vnfd_obj = utils.get_dummy_vnfd_obj()
result = self.vnfm_plugin.create_vnfd(self.context, vnfd_obj)
self.assertIsNotNone(result)
self.assertIn('id', result)
self.assertEqual('dummy_vnfd', result['name'])
self.assertEqual('dummy_vnfd_description', result['description'])
self.assertEqual('dummy_mgmt_driver', result['mgmt_driver'])
self.assertIn('service_types', result)
self.assertIn('attributes', result)
self.assertIn('created_at', result)
self.assertIn('updated_at', result)
self._device_manager.invoke.assert_called_once_with(
mock.ANY,
mock.ANY,
plugin=mock.ANY,
context=mock.ANY,
vnfd=mock.ANY)
yaml_dict = yaml.safe_load(utils.vnfd_openwrt)
mock_tosca_template.assert_called_once_with(
a_file=False, yaml_dict_tpl=yaml_dict)
mock_get_mgmt_driver.assert_called_once_with(mock.ANY)
mock_update_imports.assert_called_once_with(yaml_dict)
self._cos_db_plugin.create_event.assert_called_once_with(
self.context, evt_type=constants.RES_EVT_CREATE, res_id=mock.ANY,
res_state=constants.RES_EVT_VNFD_NA_STATE,
@ -182,13 +192,6 @@ class TestVNFMPlugin(db_base.SqlTestCase):
self.vnfm_plugin.create_vnfd,
self.context, vnfd_obj)
def test_create_vnfd_no_mgmt_driver(self):
vnfd_obj = utils.get_dummy_vnfd_obj()
vnfd_obj['vnfd'].pop('mgmt_driver')
self.assertRaises(vnfm.MGMTDriverNotSpecified,
self.vnfm_plugin.create_vnfd,
self.context, vnfd_obj)
def test_create_vnf(self):
self._insert_dummy_device_template()
vnf_obj = utils.get_dummy_vnf_obj()
@ -201,7 +204,8 @@ class TestVNFMPlugin(db_base.SqlTestCase):
self.assertIn('mgmt_url', result)
self.assertIn('created_at', result)
self.assertIn('updated_at', result)
self._device_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
self._device_manager.invoke.assert_called_with('test_vim',
'create',
plugin=mock.ANY,
context=mock.ANY,
vnf=mock.ANY,
@ -233,7 +237,7 @@ class TestVNFMPlugin(db_base.SqlTestCase):
dummy_device_obj = self._insert_dummy_device()
self.vnfm_plugin.delete_vnf(self.context, dummy_device_obj[
'id'])
self._device_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
self._device_manager.invoke.assert_called_with('test_vim', 'delete',
plugin=mock.ANY,
context=mock.ANY,
vnf_id=mock.ANY,
@ -241,7 +245,8 @@ class TestVNFMPlugin(db_base.SqlTestCase):
region_name=mock.ANY)
self._vnf_monitor.delete_hosting_vnf.assert_called_with(mock.ANY)
self._pool.spawn_n.assert_called_once_with(mock.ANY, mock.ANY,
mock.ANY, mock.ANY)
mock.ANY, mock.ANY,
mock.ANY)
self._cos_db_plugin.create_event.assert_called_with(
self.context, evt_type=constants.RES_EVT_DELETE, res_id=mock.ANY,
res_state=mock.ANY, res_type=constants.RES_TYPE_VNF,
@ -261,7 +266,8 @@ class TestVNFMPlugin(db_base.SqlTestCase):
self.assertIn('mgmt_url', result)
self.assertIn('updated_at', result)
self._pool.spawn_n.assert_called_once_with(mock.ANY, mock.ANY,
mock.ANY, mock.ANY)
mock.ANY, mock.ANY,
mock.ANY)
self._cos_db_plugin.create_event.assert_called_with(
self.context, evt_type=constants.RES_EVT_UPDATE, res_id=mock.ANY,
res_state=mock.ANY, res_type=constants.RES_TYPE_VNF,

View File

@ -26,7 +26,7 @@ class TestVIMClient(base.TestCase):
def setUp(self):
super(TestVIMClient, self).setUp()
self.vim_info = {'id': 'aaaa', 'name': 'VIM0',
'auth_cred': {'password': '****'}}
'auth_cred': {'password': '****'}, 'type': 'test_vim'}
def test_get_vim_without_defined_default_vim(self):
cfg.CONF.set_override(

View File

@ -23,6 +23,7 @@ from oslo_config import cfg
from oslo_log import log as logging
from oslo_log import versionutils
from oslo_utils import excutils
from toscaparser.tosca_template import ToscaTemplate
from tacker._i18n import _LE
from tacker.api.v1 import attributes
@ -34,6 +35,7 @@ from tacker.extensions import vnfm
from tacker.plugins.common import constants
from tacker.vnfm.mgmt_drivers import constants as mgmt_constants
from tacker.vnfm import monitor
from tacker.vnfm.tosca import utils as toscautils
from tacker.vnfm import vim_client
LOG = logging.getLogger(__name__)
@ -112,7 +114,7 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
"""
OPTS = [
cfg.ListOpt(
'infra_driver', default=['nova', 'heat', 'noop'],
'infra_driver', default=['nova', 'heat', 'noop', 'openstack'],
help=_('Hosting vnf drivers tacker plugin will use')),
]
cfg.CONF.register_opts(OPTS, 'tacker')
@ -149,16 +151,12 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
LOG.debug(_('vnfd %s'), vnfd_data)
infra_driver = vnfd_data.get('infra_driver')
if not attributes.is_attr_set(infra_driver):
LOG.debug(_('hosting vnf driver must be specified'))
raise vnfm.InfraDriverNotSpecified()
if infra_driver not in self._vnf_manager:
LOG.debug(_('unknown hosting vnf driver '
'%(infra_driver)s in %(drivers)s'),
{'infra_driver': infra_driver,
'drivers': cfg.CONF.tacker.infra_driver})
raise vnfm.InvalidInfraDriver(infra_driver=infra_driver)
if 'infra_driver' in vnfd_data or 'mgmt_driver' in vnfd_data:
versionutils.report_deprecated_feature(LOG, "Deriving "
"infra_driver and mgmt_driver from VNFD API is deprecated and"
" will be removed in Ocata. infra_driver will be automatically"
" derived from target vim type. mgmt_driver will be derived "
"from TOSCA template values.")
service_types = vnfd_data.get('service_types')
if not attributes.is_attr_set(service_types):
@ -170,13 +168,68 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
# so doesn't check it here yet.
pass
self._vnf_manager.invoke(
infra_driver, 'create_vnfd_pre', plugin=self,
context=context, vnfd=vnfd)
self._parse_template_input(vnfd)
return super(VNFMPlugin, self).create_vnfd(
context, vnfd)
def _parse_template_input(self, vnfd):
vnfd_dict = vnfd['vnfd']
vnfd_yaml = vnfd_dict['attributes'].get('vnfd')
if vnfd_yaml is None:
return
inner_vnfd_dict = yaml.load(vnfd_yaml)
LOG.debug(_('vnfd_dict: %s'), inner_vnfd_dict)
if 'tosca_definitions_version' in inner_vnfd_dict:
# Prepend the tacker_defs.yaml import file with the full
# path to the file
toscautils.updateimports(inner_vnfd_dict)
try:
tosca = ToscaTemplate(a_file=False,
yaml_dict_tpl=inner_vnfd_dict)
except Exception as e:
LOG.exception(_("tosca-parser error: %s"), str(e))
raise vnfm.ToscaParserFailed(error_msg_details=str(e))
if ('description' not in vnfd_dict or
vnfd_dict['description'] == ''):
vnfd_dict['description'] = inner_vnfd_dict.get(
'description', '')
if (('name' not in vnfd_dict or
not len(vnfd_dict['name'])) and
'metadata' in inner_vnfd_dict):
vnfd_dict['name'] = inner_vnfd_dict['metadata'].get(
'template_name', '')
vnfd_dict['mgmt_driver'] = toscautils.get_mgmt_driver(
tosca)
else:
KEY_LIST = (('name', 'template_name'),
('description', 'description'))
vnfd_dict.update(
dict((key, inner_vnfd_dict[vnfd_key]) for (key, vnfd_key)
in KEY_LIST
if ((key not in vnfd_dict or
vnfd_dict[key] == '') and
vnfd_key in inner_vnfd_dict and
inner_vnfd_dict[vnfd_key] != '')))
service_types = inner_vnfd_dict.get(
'service_properties', {}).get('type', [])
if service_types:
vnfd_dict.setdefault('service_types', []).extend(
[{'service_type': service_type}
for service_type in service_types])
# TODO(anyone) - this code assumes one mgmt_driver per VNFD???
for vdu in inner_vnfd_dict.get('vdus', {}).values():
mgmt_driver = vdu.get('mgmt_driver')
if mgmt_driver:
vnfd_dict['mgmt_driver'] = mgmt_driver
LOG.debug(_('vnfd %s'), vnfd)
def add_vnf_to_monitor(self, vnf_dict, vim_auth):
dev_attrs = vnf_dict['attributes']
mgmt_url = vnf_dict['mgmt_url']
@ -207,8 +260,11 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
}
self.update_vnf(context, vnf_id, update)
def _create_vnf_wait(self, context, vnf_dict, auth_attr):
driver_name = self._infra_driver_name(vnf_dict)
def _get_infra_driver(self, context, vnf_info):
vim_res = self.get_vim(context, vnf_info)
return vim_res['vim_type'], vim_res['vim_auth']
def _create_vnf_wait(self, context, vnf_dict, auth_attr, driver_name):
vnf_id = vnf_dict['id']
instance_id = self._instance_id(vnf_dict)
create_failed = False
@ -263,13 +319,12 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
region_name)
vnf['placement_attr']['vim_name'] = vim_res['vim_name']
vnf['vim_id'] = vim_res['vim_id']
return vim_res['vim_auth']
return vim_res
def _create_vnf(self, context, vnf, vim_auth):
def _create_vnf(self, context, vnf, vim_auth, driver_name):
vnf_dict = self._create_vnf_pre(
context, vnf) if not vnf.get('id') else vnf
vnf_id = vnf_dict['id']
driver_name = self._infra_driver_name(vnf_dict)
LOG.debug(_('vnf_dict %s'), vnf_dict)
self.mgmt_create_pre(context, vnf_dict)
try:
@ -308,11 +363,18 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
vnf_attributes['config'] = yaml.safe_dump(config)
else:
self._report_deprecated_yaml_str()
vim_auth = self.get_vim(context, vnf_info)
vnf_dict = self._create_vnf(context, vnf_info, vim_auth)
infra_driver, vim_auth = self._get_infra_driver(context, vnf_info)
if infra_driver not in self._vnf_manager:
LOG.debug(_('unknown vim driver '
'%(infra_driver)s in %(drivers)s'),
{'infra_driver': infra_driver,
'drivers': cfg.CONF.tacker.infra_driver})
raise vnfm.InvalidInfraDriver(vim_name=infra_driver)
vnf_dict = self._create_vnf(context, vnf_info, vim_auth, infra_driver)
def create_vnf_wait():
self._create_vnf_wait(context, vnf_dict, vim_auth)
self._create_vnf_wait(context, vnf_dict, vim_auth, infra_driver)
if vnf_dict['status'] is not constants.ERROR:
self.add_vnf_to_monitor(vnf_dict, vim_auth)
self.config_vnf(context, vnf_dict)
@ -322,13 +384,12 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
# not for wsgi, but for service to create hosting vnf
# the vnf is NOT added to monitor.
def create_vnf_sync(self, context, vnf):
vim_auth = self.get_vim(context, vnf)
vnf_dict = self._create_vnf(context, vnf, vim_auth)
self._create_vnf_wait(context, vnf_dict, vim_auth)
infra_driver, vim_auth = self._get_infra_driver(context, vnf)
vnf_dict = self._create_vnf(context, vnf, vim_auth, infra_driver)
self._create_vnf_wait(context, vnf_dict, vim_auth, infra_driver)
return vnf_dict
def _update_vnf_wait(self, context, vnf_dict, vim_auth):
driver_name = self._infra_driver_name(vnf_dict)
def _update_vnf_wait(self, context, vnf_dict, vim_auth, driver_name):
instance_id = self._instance_id(vnf_dict)
kwargs = {
mgmt_constants.KEY_ACTION: mgmt_constants.ACTION_UPDATE_VNF,
@ -368,8 +429,7 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
else:
self._report_deprecated_yaml_str()
vnf_dict = self._update_vnf_pre(context, vnf_id)
vim_auth = self.get_vim(context, vnf_dict)
driver_name = self._infra_driver_name(vnf_dict)
driver_name, vim_auth = self._get_infra_driver(context, vnf_dict)
instance_id = self._instance_id(vnf_dict)
try:
@ -388,11 +448,11 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
self.mgmt_update_post(context, vnf_dict)
self._update_vnf_post(context, vnf_id, constants.ERROR)
self.spawn_n(self._update_vnf_wait, context, vnf_dict, vim_auth)
self.spawn_n(self._update_vnf_wait, context, vnf_dict, vim_auth,
driver_name)
return vnf_dict
def _delete_vnf_wait(self, context, vnf_dict, auth_attr):
driver_name = self._infra_driver_name(vnf_dict)
def _delete_vnf_wait(self, context, vnf_dict, auth_attr, driver_name):
instance_id = self._instance_id(vnf_dict)
e = None
if instance_id:
@ -419,9 +479,8 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
def delete_vnf(self, context, vnf_id):
vnf_dict = self._delete_vnf_pre(context, vnf_id)
vim_auth = self.get_vim(context, vnf_dict)
driver_name, vim_auth = self._get_infra_driver(context, vnf_dict)
self._vnf_monitor.delete_hosting_vnf(vnf_id)
driver_name = self._infra_driver_name(vnf_dict)
instance_id = self._instance_id(vnf_dict)
placement_attr = vnf_dict['placement_attr']
region_name = placement_attr.get('region_name')
@ -450,7 +509,8 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
self.mgmt_delete_post(context, vnf_dict)
self._delete_vnf_post(context, vnf_id, e)
self.spawn_n(self._delete_vnf_wait, context, vnf_dict, vim_auth)
self.spawn_n(self._delete_vnf_wait, context, vnf_dict, vim_auth,
driver_name)
def _handle_vnf_scaling(self, context, policy):
# validate
@ -567,8 +627,7 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
vnf = _handle_vnf_scaling_pre()
policy['instance_id'] = vnf['instance_id']
infra_driver = self._infra_driver_name(vnf)
vim_auth = self.get_vim(context, vnf)
infra_driver, vim_auth = self._get_infra_driver(context, vnf)
region_name = vnf.get('placement_attr', {}).get('region_name', None)
last_event_id = _vnf_policy_action()
self.spawn_n(_vnf_policy_action_wait)
@ -637,15 +696,14 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
def get_vnf_resources(self, context, vnf_id, fields=None, filters=None):
vnf_info = self.get_vnf(context, vnf_id)
infra_driver = vnf_info['vnfd']['infra_driver']
auth = self.get_vim(context, vnf_info)
infra_driver, vim_auth = self._get_infra_driver(context, vnf_info)
if vnf_info['status'] == constants.ACTIVE:
vnf_details = self._vnf_manager.invoke(infra_driver,
'get_resource_info',
plugin=self,
context=context,
vnf_info=vnf_info,
auth_attr=auth)
auth_attr=vim_auth)
resources = [{'name': name,
'type': info.get('type'),
'id': info.get('id')}

View File

@ -38,11 +38,6 @@ class DeviceAbstractDriver(extensions.PluginInterface):
def get_description(self):
pass
# @abc.abstractmethod
def create_vnfd_pre(self, plugin, context, vnfd):
"""Called before creating vnf template."""
pass
@abc.abstractmethod
def create(self, plugin, context, vnf):
"""Create vnf and return its id."""

View File

@ -52,15 +52,12 @@ OPTS = [
help=_("Flavor Extra Specs")),
]
CONF.register_opts(OPTS, group='tacker_heat')
CONF.register_opts(OPTS, group='openstack_vim')
def config_opts():
return [('tacker_heat', OPTS)]
return [('openstack_vim', OPTS)]
STACK_RETRIES = cfg.CONF.tacker_heat.stack_retries
STACK_RETRY_WAIT = cfg.CONF.tacker_heat.stack_retry_wait
STACK_FLAVOR_EXTRA = cfg.CONF.tacker_heat.flavor_extra_specs
# Global map of individual resource type and
# incompatible properties, alternate properties pair for
@ -83,80 +80,24 @@ def get_scaling_policy_name(action, policy_name):
return '%s_scale_%s' % (policy_name, action)
class DeviceHeat(abstract_driver.DeviceAbstractDriver,
scale_driver.VnfScaleAbstractDriver):
"""Heat driver of hosting vnf."""
class OpenStack(abstract_driver.DeviceAbstractDriver,
scale_driver.VnfScaleAbstractDriver):
"""Openstack infra driver for hosting vnfs"""
def __init__(self):
super(DeviceHeat, self).__init__()
super(OpenStack, self).__init__()
self.STACK_RETRIES = cfg.CONF.openstack_vim.stack_retries
self.STACK_RETRY_WAIT = cfg.CONF.openstack_vim.stack_retry_wait
self.STACK_FLAVOR_EXTRA = cfg.CONF.openstack_vim.flavor_extra_specs
def get_type(self):
return 'heat'
return 'openstack'
def get_name(self):
return 'heat'
return 'openstack'
def get_description(self):
return 'Heat infra driver'
@log.log
def create_vnfd_pre(self, plugin, context, vnfd):
vnfd_dict = vnfd['vnfd']
vnfd_yaml = vnfd_dict['attributes'].get('vnfd')
if vnfd_yaml is None:
return
inner_vnfd_dict = yaml.load(vnfd_yaml)
LOG.debug(_('vnfd_dict: %s'), inner_vnfd_dict)
if 'tosca_definitions_version' in inner_vnfd_dict:
# Prepend the tacker_defs.yaml import file with the full
# path to the file
toscautils.updateimports(inner_vnfd_dict)
try:
tosca = tosca_template.ToscaTemplate(
a_file=False, yaml_dict_tpl=inner_vnfd_dict)
except Exception as e:
LOG.exception(_("tosca-parser error: %s"), str(e))
raise vnfm.ToscaParserFailed(error_msg_details=str(e))
if ('description' not in vnfd_dict or
vnfd_dict['description'] == ''):
vnfd_dict['description'] = inner_vnfd_dict.get(
'description', '')
if (('name' not in vnfd_dict or
not len(vnfd_dict['name'])) and
'metadata' in inner_vnfd_dict):
vnfd_dict['name'] = inner_vnfd_dict['metadata'].get(
'template_name', '')
vnfd_dict['mgmt_driver'] = toscautils.get_mgmt_driver(
tosca)
else:
KEY_LIST = (('name', 'template_name'),
('description', 'description'))
vnfd_dict.update(
dict((key, inner_vnfd_dict[vnfd_key]) for (key, vnfd_key)
in KEY_LIST
if ((key not in vnfd_dict or
vnfd_dict[key] == '') and
vnfd_key in inner_vnfd_dict and
inner_vnfd_dict[vnfd_key] != '')))
service_types = inner_vnfd_dict.get(
'service_properties', {}).get('type', [])
if service_types:
vnfd_dict.setdefault('service_types', []).extend(
[{'service_type': service_type}
for service_type in service_types])
# TODO(anyone) - this code assumes one mgmt_driver per VNFD???
for vdu in inner_vnfd_dict.get('vdus', {}).values():
mgmt_driver = vdu.get('mgmt_driver')
if mgmt_driver:
vnfd_dict['mgmt_driver'] = mgmt_driver
LOG.debug(_('vnfd %s'), vnfd)
return 'Openstack infra driver'
@log.log
def _update_params(self, original, paramvalues, match=False):
@ -332,7 +273,7 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
monitoring_dict = toscautils.get_vdu_monitoring(tosca)
mgmt_ports = toscautils.get_mgmt_ports(tosca)
res_tpl = toscautils.get_resources_dict(tosca,
STACK_FLAVOR_EXTRA)
self.STACK_FLAVOR_EXTRA)
toscautils.post_process_template(tosca)
try:
translator = tosca_translator.TOSCATranslator(tosca,
@ -611,10 +552,10 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
stack = heatclient_.get(vnf_id)
status = stack.stack_status
stack_retries = STACK_RETRIES
stack_retries = self.STACK_RETRIES
error_reason = None
while status == 'CREATE_IN_PROGRESS' and stack_retries > 0:
time.sleep(STACK_RETRY_WAIT)
time.sleep(self.STACK_RETRY_WAIT)
try:
stack = heatclient_.get(vnf_id)
except Exception:
@ -633,7 +574,8 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
error_reason = _("Resource creation is not completed within"
" {wait} seconds as creation of stack {stack}"
" is not completed").format(
wait=(STACK_RETRIES * STACK_RETRY_WAIT),
wait=(self.STACK_RETRIES *
self.STACK_RETRY_WAIT),
stack=vnf_id)
LOG.warning(_("VNF Creation failed: %(reason)s"),
{'reason': error_reason})
@ -727,9 +669,9 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
stack = heatclient_.get(vnf_id)
status = stack.stack_status
error_reason = None
stack_retries = STACK_RETRIES
stack_retries = self.STACK_RETRIES
while (status == 'DELETE_IN_PROGRESS' and stack_retries > 0):
time.sleep(STACK_RETRY_WAIT)
time.sleep(self.STACK_RETRY_WAIT)
try:
stack = heatclient_.get(vnf_id)
except heatException.HTTPNotFound:
@ -748,7 +690,7 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
" not completed within {wait} seconds as "
"deletion of Stack {stack} is "
"not completed").format(stack=vnf_id,
wait=(STACK_RETRIES * STACK_RETRY_WAIT))
wait=(self.STACK_RETRIES * self.STACK_RETRY_WAIT))
LOG.warning(error_reason)
raise vnfm.VNFCreateWaitFailed(vnf_id=vnf_id,
reason=error_reason)
@ -832,10 +774,10 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
# TODO(kanagaraj-manickam) make wait logic into separate utility method
# and make use of it here and other actions like create and delete
stack_retries = STACK_RETRIES
stack_retries = self.STACK_RETRIES
while (True):
try:
time.sleep(STACK_RETRY_WAIT)
time.sleep(self.STACK_RETRY_WAIT)
stack_id = policy['instance_id']
policy_name = get_scaling_policy_name(
policy_name=policy['id'],
@ -873,7 +815,8 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
"VNF scaling failed to complete within %{wait}s seconds "
"while waiting for the stack %(stack)s to be "
"scaled.") % {'stack': stack_id,
'wait': STACK_RETRIES * STACK_RETRY_WAIT}
'wait': self.STACK_RETRIES *
self.STACK_RETRY_WAIT}
LOG.warning(error_reason)
raise vnfm.VNFScaleWaitFailed(
vnf_id=policy['vnf']['id'],

View File

@ -0,0 +1,69 @@
# Copyright 2015 Intel Corporation.
# 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 oslo_config import cfg
from oslo_log import log as logging
from oslo_log import versionutils
from tacker.vnfm.infra_drivers.openstack import openstack
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
OPTS = [
cfg.IntOpt('stack_retries',
default=60,
help=_("Number of attempts to retry for stack"
" creation/deletion")),
cfg.IntOpt('stack_retry_wait',
default=5,
help=_("Wait time (in seconds) between consecutive stack"
" create/delete retries")),
cfg.DictOpt('flavor_extra_specs',
default={},
help=_("Flavor Extra Specs")),
]
CONF.register_opts(OPTS, group='tacker_heat')
def config_opts():
return [('tacker_heat', OPTS)]
class VimHeat(openstack.OpenStack):
"""Heat driver of hosting vnf."""
@versionutils.deprecated(
versionutils.deprecated.NEWTON,
what='infra_driver heat',
in_favor_of='infra_driver openstack',
remove_in=+1)
def __init__(self):
super(VimHeat, self).__init__()
self.STACK_RETRIES = cfg.CONF.tacker_heat.stack_retries
self.STACK_RETRY_WAIT = cfg.CONF.tacker_heat.stack_retry_wait
self.STACK_FLAVOR_EXTRA = cfg.CONF.tacker_heat.flavor_extra_specs
def get_type(self):
return 'heat'
def get_name(self):
return 'heat'
def get_description(self):
return 'Heat infra driver'

View File

@ -30,7 +30,7 @@ from tacker.common import driver_manager
from tacker import context as t_context
from tacker.db.common_services import common_services_db
from tacker.plugins.common import constants
from tacker.vnfm.infra_drivers.heat import heat
from tacker.vnfm.infra_drivers.openstack import openstack
LOG = logging.getLogger(__name__)
@ -279,7 +279,7 @@ class ActionRespawnHeat(ActionPolicy):
placement_attr = vnf_dict.get('placement_attr', {})
region_name = placement_attr.get('region_name')
# kill heat stack
heatclient = heat.HeatClient(auth_attr=auth_attr,
heatclient = openstack.HeatClient(auth_attr=auth_attr,
region_name=region_name)
heatclient.delete(vnf_dict['instance_id'])

View File

@ -81,7 +81,8 @@ class VimClient(object):
vim_auth = self._build_vim_auth(vim_info)
vim_res = {'vim_auth': vim_auth, 'vim_id': vim_info['id'],
'vim_name': vim_info.get('name', vim_info['id'])}
'vim_name': vim_info.get('name', vim_info['id']),
'vim_type': vim_info['type']}
return vim_res
@staticmethod