Merge "Add VNF resource details to get vnf API"
This commit is contained in:
commit
427cfb6d58
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Added API to fetch VNF components details.
|
@ -140,6 +140,15 @@ class FilePathMissing(exceptions.InvalidInput):
|
||||
"tosca.artifacts.Deployment.Image.VM artifact type")
|
||||
|
||||
|
||||
class InfraDriverUnreachable(exceptions.ServiceUnavailable):
|
||||
message = _("Could not retrieve VNF resource IDs and"
|
||||
" types. Please check %(service)s status.")
|
||||
|
||||
|
||||
class VNFInactive(exceptions.InvalidInput):
|
||||
message = _("VNF %(vnf_id)s is not in Active state %(message)s")
|
||||
|
||||
|
||||
def _validate_service_type_list(data, valid_values=None):
|
||||
if not isinstance(data, list):
|
||||
msg = _("invalid data format for service list: '%s'") % data
|
||||
@ -358,6 +367,33 @@ SUB_RESOURCE_ATTRIBUTE_MAP = {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'resources': {
|
||||
'parent': {
|
||||
'collection_name': 'vnfs',
|
||||
'member_name': 'vnf'
|
||||
},
|
||||
'members': {
|
||||
'resource': {
|
||||
'parameters': {
|
||||
'name': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
'type': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
'id': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,6 +500,10 @@ class VNFMPluginBase(service_base.NFVPluginBase):
|
||||
def get_vnf(self, context, vnf_id, fields=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_vnf_resources(self, context, vnf_id, fields=None, filters=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_vnf(self, context, vnf):
|
||||
pass
|
||||
|
@ -53,6 +53,12 @@ class VnfTestCreate(base.BaseTackerTest):
|
||||
if vim_id:
|
||||
self.assertEqual(vim_id, vnf_instance['vnf']['vim_id'])
|
||||
|
||||
# Get vnf details when vnf is in active state
|
||||
vnf_details = self.client.list_vnf_resources(vnf_id)['resources'][0]
|
||||
self.assertIn('name', vnf_details)
|
||||
self.assertIn('id', vnf_details)
|
||||
self.assertIn('type', vnf_details)
|
||||
|
||||
# Delete vnf_instance with vnf_id
|
||||
try:
|
||||
self.client.delete_vnf(vnf_id)
|
||||
|
@ -20,6 +20,7 @@ import os
|
||||
import yaml
|
||||
|
||||
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
|
||||
@ -143,6 +144,28 @@ class TestDeviceHeat(base.TestCase):
|
||||
'id': 'eb84260e-5ff7-4332-b032-50a14d6c1123', 'description':
|
||||
u'OpenWRT with services'}
|
||||
|
||||
def _get_expected_active_vnf(self):
|
||||
return {'status': 'ACTIVE',
|
||||
'instance_id': None,
|
||||
'name': u'test_openwrt',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'vnfd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'vnfd': {
|
||||
'service_types': [{
|
||||
'service_type': u'vnfd',
|
||||
'id': 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': '{"vdu1": "192.168.120.31"}',
|
||||
'service_context': [],
|
||||
'id': 'eb84260e-5ff7-4332-b032-50a14d6c1123',
|
||||
'description': u'OpenWRT with services'}
|
||||
|
||||
def test_create(self):
|
||||
vnf_obj = utils.get_dummy_device_obj()
|
||||
expected_result = '4a4c2d44-8a52-4895-9a75-9d1c76c3e738'
|
||||
@ -408,3 +431,12 @@ class TestDeviceHeat(base.TestCase):
|
||||
files={'scaling.yaml': 'hot_scale_custom.yaml'},
|
||||
is_monitor=False
|
||||
)
|
||||
|
||||
def test_get_resource_info(self):
|
||||
vnf_obj = self._get_expected_active_vnf()
|
||||
print(vnf_obj)
|
||||
self.assertRaises(vnfm.InfraDriverUnreachable,
|
||||
self.heat_driver.get_resource_info,
|
||||
plugin=None, context=self.context, vnf_info=vnf_obj,
|
||||
auth_attr=utils.get_vim_auth_obj(),
|
||||
region_name=None)
|
||||
|
@ -32,6 +32,10 @@ class FakeDriverManager(mock.Mock):
|
||||
def invoke(self, *args, **kwargs):
|
||||
if 'create' in args:
|
||||
return str(uuid.uuid4())
|
||||
if 'get_resource_info' in args:
|
||||
return {'resources': {'name': 'dummy_vnf',
|
||||
'type': 'dummy',
|
||||
'id': str(uuid.uuid4())}}
|
||||
|
||||
|
||||
class FakeVNFMonitor(mock.Mock):
|
||||
@ -208,6 +212,22 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
||||
res_state=mock.ANY, res_type=constants.RES_TYPE_VNF,
|
||||
tstamp=mock.ANY, details=mock.ANY)
|
||||
|
||||
def test_show_vnf_details_vnf_inactive(self):
|
||||
self._insert_dummy_device_template()
|
||||
vnf_obj = utils.get_dummy_vnf_obj()
|
||||
result = self.vnfm_plugin.create_vnf(self.context, vnf_obj)
|
||||
self.assertRaises(vnfm.VNFInactive, self.vnfm_plugin.get_vnf_resources,
|
||||
self.context, result['id'])
|
||||
|
||||
def test_show_vnf_details_vnf_active(self):
|
||||
self._insert_dummy_device_template()
|
||||
active_vnf = self._insert_dummy_device()
|
||||
resources = self.vnfm_plugin.get_vnf_resources(self.context,
|
||||
active_vnf['id'])[0]
|
||||
self.assertIn('name', resources)
|
||||
self.assertIn('type', resources)
|
||||
self.assertIn('id', resources)
|
||||
|
||||
def test_delete_vnf(self):
|
||||
self._insert_dummy_device_template()
|
||||
dummy_device_obj = self._insert_dummy_device()
|
||||
|
@ -629,3 +629,24 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
self._handle_vnf_scaling(context, policy_)
|
||||
|
||||
return scale['scale']
|
||||
|
||||
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)
|
||||
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)
|
||||
resources = [{'name': name,
|
||||
'type': info.get('type'),
|
||||
'id': info.get('id')}
|
||||
for name, info in vnf_details.items()]
|
||||
return resources
|
||||
# Raise exception when VNF.status != ACTIVE
|
||||
else:
|
||||
raise vnfm.VNFInactive(vnf_id=vnf_id,
|
||||
message=_(' Cannot fetch details'))
|
||||
|
@ -68,3 +68,9 @@ class DeviceAbstractDriver(extensions.PluginInterface):
|
||||
@abc.abstractmethod
|
||||
def delete_wait(self, plugin, context, vnf_id):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_resource_info(self, plugin, context, vnf_info, auth_attr,
|
||||
region_name=None):
|
||||
'''Fetches optional details of a VNF'''
|
||||
pass
|
||||
|
@ -855,6 +855,21 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver,
|
||||
|
||||
return jsonutils.dumps(mgmt_ips)
|
||||
|
||||
def get_resource_info(self, plugin, context, vnf_info, auth_attr,
|
||||
region_name=None):
|
||||
stack_id = vnf_info['instance_id']
|
||||
heatclient_ = HeatClient(auth_attr, region_name)
|
||||
try:
|
||||
resources_ids = heatclient_.resource_get_list(stack_id)
|
||||
details_dict = {resource.resource_name:
|
||||
{"id": resource.physical_resource_id,
|
||||
"type": resource.resource_type}
|
||||
for resource in resources_ids}
|
||||
return details_dict
|
||||
# Raise exception when Heat API service is not available
|
||||
except Exception:
|
||||
raise vnfm.InfraDriverUnreachable(service="Heat API service")
|
||||
|
||||
|
||||
class HeatClient(object):
|
||||
def __init__(self, auth_attr, region_name=None):
|
||||
@ -862,6 +877,7 @@ class HeatClient(object):
|
||||
self.heat = clients.OpenstackClients(auth_attr, region_name).heat
|
||||
self.stacks = self.heat.stacks
|
||||
self.resource_types = self.heat.resource_types
|
||||
self.resources = self.heat.resources
|
||||
|
||||
def create(self, fields):
|
||||
fields = fields.copy()
|
||||
|
Loading…
Reference in New Issue
Block a user