Tacker: ETSI MANO NFV Orchestrator / VNF Manager. See https://wiki.openstack.org/wiki/Tacker
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4199 lines
182 KiB
4199 lines
182 KiB
# Copyright (C) 2020 NTT DATA |
|
# 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 codecs |
|
import copy |
|
import ddt |
|
from http import client as http_client |
|
import json |
|
import os |
|
from unittest import mock |
|
import urllib |
|
import webob |
|
from webob import exc |
|
|
|
from oslo_config import cfg |
|
from oslo_serialization import jsonutils |
|
|
|
from tacker.api.views import vnf_subscriptions as vnf_subscription_view |
|
from tacker.api.vnflcm.v1 import controller |
|
from tacker.api.vnflcm.v1 import sync_resource |
|
from tacker.common import exceptions |
|
from tacker.common import utils as common_utils |
|
import tacker.conductor.conductorrpc.vnf_lcm_rpc as vnf_lcm_rpc |
|
from tacker import context |
|
import tacker.db.vnfm.vnfm_db |
|
from tacker.extensions import nfvo |
|
from tacker.extensions import vnfm |
|
from tacker.manager import TackerManager |
|
from tacker import objects |
|
from tacker.objects import fields |
|
from tacker.objects import vnf_lcm_subscriptions as subscription_obj |
|
from tacker.tests import constants |
|
from tacker.tests.unit import base |
|
from tacker.tests.unit.db import utils |
|
from tacker.tests.unit import fake_request |
|
import tacker.tests.unit.nfvo.test_nfvo_plugin as test_nfvo_plugin |
|
from tacker.tests.unit.vnflcm import fakes |
|
from tacker.tests import uuidsentinel |
|
import tacker.vnfm.nfvo_client as nfvo_client |
|
from tacker.vnfm import vim_client |
|
|
|
|
|
class FakeVimClient(mock.Mock): |
|
pass |
|
|
|
|
|
def _get_template(name): |
|
filename = os.path.abspath(os.path.join(os.path.dirname(__file__), |
|
'../../etc/samples/' + str(name))) |
|
f = codecs.open(filename, encoding='utf-8', errors='strict') |
|
return f.read() |
|
|
|
|
|
class FakeVNFMPlugin(mock.Mock): |
|
|
|
def __init__(self): |
|
super(FakeVNFMPlugin, self).__init__() |
|
self.vnf1_vnfd_id = 'eb094833-995e-49f0-a047-dfb56aaf7c4e' |
|
self.vnf1_vnf_id = '91e32c20-6d1f-47a4-9ba7-08f5e5effe07' |
|
self.vnf1_update_vnf_id = '91e32c20-6d1f-47a4-9ba7-08f5e5effaf6' |
|
self.vnf2_vnfd_id = 'e4015e9f-1ef2-49fb-adb6-070791ad3c45' |
|
self.vnf3_vnfd_id = 'e4015e9f-1ef2-49fb-adb6-070791ad3c45' |
|
self.vnf3_vnf_id = '7168062e-9fa1-4203-8cb7-f5c99ff3ee1b' |
|
self.vnf3_update_vnf_id = '10f66bc5-b2f1-45b7-a7cd-6dd6ad0017f5' |
|
self.vnf_for_cnf_vnfd_id = 'e889e4fe-52fe-437d-b1e1-a690dc95e3f8' |
|
self.vnf_for_cnf_vnf_id = '436aaa6e-2db6-4d6e-a3fc-e728b2f0ac56' |
|
|
|
self.cp11_id = 'd18c8bae-898a-4932-bff8-d5eac981a9c9' |
|
self.cp11_update_id = 'a18c8bae-898a-4932-bff8-d5eac981a9b8' |
|
self.cp12_id = 'c8906342-3e30-4b2a-9401-a251a7a9b5dd' |
|
self.cp12_update_id = 'b8906342-3e30-4b2a-9401-a251a7a9b5cc' |
|
self.cp32_id = '3d1bd2a2-bf0e-44d1-87af-a2c6b2cad3ed' |
|
self.cp32_update_id = '064c0d99-5a61-4711-9597-2a44dc5da14b' |
|
|
|
def get_vnfd(self, *args, **kwargs): |
|
if 'VNF1' in args: |
|
return {'id': self.vnf1_vnfd_id, |
|
'name': 'VNF1', |
|
'attributes': {'vnfd': _get_template( |
|
'test-nsd-vnfd1.yaml')}} |
|
elif 'VNF2' in args: |
|
return {'id': self.vnf3_vnfd_id, |
|
'name': 'VNF2', |
|
'attributes': {'vnfd': _get_template( |
|
'test-nsd-vnfd2.yaml')}} |
|
|
|
def get_vnfds(self, *args, **kwargs): |
|
if {'name': ['VNF1']} in args: |
|
return [{'id': self.vnf1_vnfd_id}] |
|
elif {'name': ['VNF3']} in args: |
|
return [{'id': self.vnf3_vnfd_id}] |
|
else: |
|
return [] |
|
|
|
def get_vnfs(self, *args, **kwargs): |
|
if {'vnfd_id': [self.vnf1_vnfd_id]} in args: |
|
return [{'id': self.vnf1_vnf_id}] |
|
elif {'vnfd_id': [self.vnf3_vnfd_id]} in args: |
|
return [{'id': self.vnf3_vnf_id}] |
|
else: |
|
return None |
|
|
|
def get_vnf(self, *args, **kwargs): |
|
if self.vnf1_vnf_id in args: |
|
return self.get_dummy_vnf_error() |
|
elif self.vnf3_vnf_id in args: |
|
return self.get_dummy_vnf_not_error() |
|
elif self.vnf_for_cnf_vnf_id in args: |
|
return fakes.vnf_dict_cnf() |
|
else: |
|
return self.get_dummy_vnf_active() |
|
|
|
def get_vnf_resources(self, *args, **kwargs): |
|
if self.vnf1_vnf_id in args: |
|
return self.get_dummy_vnf1_details() |
|
elif self.vnf1_update_vnf_id in args: |
|
return self.get_dummy_vnf1_update_details() |
|
elif self.vnf3_vnf_id in args: |
|
return self.get_dummy_vnf3_details() |
|
elif self.vnf3_update_vnf_id in args: |
|
return self.get_dummy_vnf3_update_details() |
|
|
|
def get_dummy_vnf1_details(self): |
|
return [{'name': 'CP11', 'id': self.cp11_id}, |
|
{'name': 'CP12', 'id': self.cp12_id}] |
|
|
|
def get_dummy_vnf1_update_details(self): |
|
return [{'name': 'CP11', 'id': self.cp11_update_id}, |
|
{'name': 'CP12', 'id': self.cp12_update_id}] |
|
|
|
def get_dummy_vnf3_details(self): |
|
return [{'name': 'CP32', 'id': self.cp32_id}] |
|
|
|
def get_dummy_vnf3_update_details(self): |
|
return [{'name': 'CP32', 'id': self.cp32_update_id}] |
|
|
|
def get_dummy_vnf_active(self): |
|
return {'tenant_id': uuidsentinel.tenant_id, |
|
'name': "fake_name", |
|
'vnfd_id': uuidsentinel.vnfd_id, |
|
'vnf_instance_id': uuidsentinel.instance_id, |
|
'mgmt_ip_address': "fake_mgmt_ip_address", |
|
'status': 'ACTIVE', |
|
'description': 'fake_description', |
|
'placement_attr': 'fake_placement_attr', |
|
'vim_id': 'uuidsentinel.vim_id', |
|
'error_reason': 'fake_error_reason', |
|
'attributes': { |
|
"scale_group": '{"scaleGroupDict":' + |
|
'{"SP1": {"maxLevel" : 3}}}'}} |
|
|
|
def get_dummy_vnf_error(self): |
|
return {'tenant_id': uuidsentinel.tenant_id, |
|
'name': "fake_name", |
|
'vnfd_id': uuidsentinel.vnfd_id, |
|
'vnf_instance_id': uuidsentinel.instance_id, |
|
'mgmt_ip_address': "fake_mgmt_ip_address", |
|
'status': 'ERROR', |
|
'description': 'fake_description', |
|
'placement_attr': 'fake_placement_attr', |
|
'vim_id': 'uuidsentinel.vim_id', |
|
'error_reason': 'fake_error_reason', |
|
'attributes': { |
|
"scale_group": '{"scaleGroupDict":' + |
|
'{"SP1": {"maxLevel" : 3}}}'}} |
|
|
|
def get_dummy_vnf_not_error(self): |
|
msg = _('VNF %(vnf_id)s could not be found') |
|
raise vnfm.VNFNotFound(explanation=msg) |
|
|
|
|
|
@ddt.ddt |
|
class TestController(base.TestCase): |
|
expected_location_prefix = ('http://localhost:9890/' |
|
'vnflcm/v1/vnf_lcm_op_occs/') |
|
|
|
def setUp(self): |
|
super(TestController, self).setUp() |
|
self.patcher = mock.patch( |
|
'tacker.manager.TackerManager.get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
self.mock_manager = self.patcher.start() |
|
self.controller = controller.VnfLcmController() |
|
self.vim_info = { |
|
'vim_id': uuidsentinel.vnfd_id, |
|
'vim_type': 'test', |
|
'vim_auth': {'username': 'test', 'password': 'test'}, |
|
'placement_attr': {'region': 'TestRegionOne'}, |
|
'tenant': 'test' |
|
} |
|
self.context = context.get_admin_context() |
|
|
|
with mock.patch.object(tacker.db.vnfm.vnfm_db.VNFMPluginDb, 'get_vnfs', |
|
return_value=[]): |
|
with mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}): |
|
self.controller = controller.VnfLcmController() |
|
|
|
def tearDown(self): |
|
self.mock_manager.stop() |
|
super(TestController, self).tearDown() |
|
|
|
@property |
|
def app(self): |
|
return fakes.wsgi_app_v1() |
|
|
|
def _get_dummy_vnf(self, vnf_id=None, status=None): |
|
vnf_dict = utils.get_dummy_vnf() |
|
|
|
if status: |
|
vnf_dict['status'] = status |
|
|
|
if vnf_id: |
|
vnf_dict['id'] = vnf_id |
|
|
|
return vnf_dict |
|
|
|
def _make_problem_detail( |
|
self, |
|
detail, |
|
status, |
|
title=None, |
|
type=None, |
|
instance=None): |
|
res = webob.Response(content_type='application/problem+json') |
|
problemDetails = {} |
|
if type: |
|
problemDetails['type'] = type |
|
if title: |
|
problemDetails['title'] = title |
|
problemDetails['detail'] = detail |
|
problemDetails['status'] = status |
|
if instance: |
|
problemDetails['instance'] = instance |
|
res.text = json.dumps(problemDetails) |
|
res.status_int = status |
|
return res |
|
|
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._update_package_usage_state') |
|
@mock.patch.object(objects.VnfPackage, 'get_by_id') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._create_vnf') |
|
@mock.patch.object(objects.vnf_package.VnfPackage, 'save') |
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.vnf_instance, '_vnf_instance_create') |
|
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd, 'get_by_id') |
|
def test_create_without_name_and_description( |
|
self, mock_get_by_id, |
|
mock_vnf_instance_create, |
|
mock_get_service_plugins, |
|
mock_package_save, |
|
mock_private_create_vnf, |
|
mock_vnf_package_get_by_id, |
|
mock_update_package_usage_state, |
|
mock_get_vim): |
|
mock_get_vim.return_value = self.vim_info |
|
mock_get_by_id.return_value = fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
|
|
updates = {'vnfd_id': uuidsentinel.vnfd_id, |
|
'vnf_instance_description': 'SampleVnf Description', |
|
'vnf_instance_name': 'SampleVnf', |
|
'vnf_pkg_id': uuidsentinel.vnf_pkg_id, |
|
'vnf_metadata': {"key": "value"}} |
|
|
|
mock_vnf_instance_create.return_value =\ |
|
fakes.return_vnf_instance_model(**updates) |
|
|
|
body = {'vnfdId': uuidsentinel.vnfd_id, |
|
"vnfInstanceName": "SampleVnf", |
|
"vnfInstanceDescription": "SampleVnf Description", |
|
'metadata': {"key": "value"}} |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Create API |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.CREATED, resp.status_code) |
|
|
|
updates = {"vnfInstanceName": "SampleVnf", |
|
"vnfInstanceDescription": "SampleVnf Description"} |
|
expected_vnf = fakes.fake_vnf_instance_response(**updates) |
|
location_header = ('http://localhost:9890/vnflcm/v1/vnf_instances/%s' |
|
% resp.json['id']) |
|
|
|
self.assertEqual(expected_vnf, resp.json) |
|
self.assertEqual(location_header, resp.headers['location']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data( |
|
{'attribute': 'vnfdId', 'value': True, |
|
'expected_type': 'uuid'}, |
|
{'attribute': 'vnfdId', 'value': 123, |
|
'expected_type': 'uuid'}, |
|
{'attribute': 'vnfInstanceName', 'value': True, |
|
'expected_type': "name_allow_zero_min_length"}, |
|
{'attribute': 'vnfInstanceName', 'value': 123, |
|
'expected_type': "name_allow_zero_min_length"}, |
|
{'attribute': 'vnfInstanceDescription', 'value': True, |
|
'expected_type': 'description'}, |
|
{'attribute': 'vnfInstanceDescription', 'value': 123, |
|
'expected_type': 'description'} |
|
) |
|
@ddt.unpack |
|
def test_create_with_invalid_request_body( |
|
self, mock_get_service_plugins, attribute, value, expected_type): |
|
"""value of attribute in body is of invalid type""" |
|
body = {"vnfInstanceName": "SampleVnf", |
|
"vnfdId": "29c770a3-02bc-4dfc-b4be-eb173ac00567", |
|
"vnfInstanceDescription": "VNF Description", |
|
"metadata": {"key": "value"}} |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
body.update({attribute: value}) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
exception = self.assertRaises( |
|
exceptions.ValidationError, self.controller.create, |
|
req, body=body) |
|
if expected_type == 'uuid': |
|
expected_message = ("Invalid input for field/attribute " |
|
"{attribute}. Value: {value}. {value} is not " |
|
"of type 'string'". |
|
format(value=value, attribute=attribute)) |
|
elif expected_type in ["name_allow_zero_min_length", "description"]: |
|
expected_message = ("Invalid input for field/attribute " |
|
"{attribute}. " "Value: {value}. {value} is " |
|
"not of type 'string'". |
|
format(value=value, attribute=attribute)) |
|
elif expected_type == 'object': |
|
expected_message = ("Invalid input for field/attribute " |
|
"{attribute}. " "Value: {value}. {value} is " |
|
"not of type {expected_type}". |
|
format(value=value, attribute=attribute, |
|
expected_type=expected_type)) |
|
|
|
self.assertEqual(expected_message, exception.msg) |
|
|
|
@mock.patch.object(sync_resource.SyncVnfPackage, 'create_package') |
|
@mock.patch.object(nfvo_client.VnfPackageRequest, "index") |
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd, 'get_by_id') |
|
def test_create_non_existing_vnf_package_vnfd(self, mock_vnf_by_id, |
|
mock_get_service_plugins, |
|
mock_index, |
|
mock_create_package): |
|
mock_vnf_by_id.side_effect = exceptions.VnfPackageVnfdNotFound |
|
mock_create_package.return_value = fakes.return_vnf_package_vnfd() |
|
mock_response = mock.MagicMock() |
|
mock_response.ok = True |
|
mock_response.json = mock.MagicMock() |
|
mock_response.json.return_value = ['aaa', 'bbb', 'ccc'] |
|
mock_index.return_value = mock_response |
|
body = {'vnfdId': uuidsentinel.vnfd_id, |
|
'metadata': {"key": "value"}} |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
self.assertRaises(exc.HTTPBadRequest, self.controller.create, req, |
|
body=body) |
|
|
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._update_package_usage_state') |
|
@mock.patch.object(objects.VnfPackage, 'get_by_id') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._create_vnf') |
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(sync_resource.SyncVnfPackage, 'create_package') |
|
@mock.patch.object(nfvo_client.VnfPackageRequest, "index") |
|
@mock.patch.object(objects.vnf_instance, '_vnf_instance_create') |
|
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd, 'get_by_id') |
|
def test_create_vnf_package_not_found( |
|
self, mock_get_by_id_package_vnfd, |
|
mock_vnf_instance_create, |
|
mock_index, mock_create_pkg, |
|
mock_get_service_plugins, |
|
mock_private_create_vnf, |
|
mock_vnf_package_get_by_id, |
|
mock_update_package_usage_state, |
|
mock_get_vim): |
|
mock_get_by_id_package_vnfd.side_effect =\ |
|
exceptions.VnfPackageVnfdNotFound |
|
|
|
mock_response = mock.MagicMock() |
|
mock_response.ok = True |
|
mock_response.json = mock.MagicMock() |
|
mock_response.json.return_value = ['aaa', 'bbb', 'ccc'] |
|
|
|
mock_index.return_value = mock_response |
|
mock_create_pkg.return_value = fakes.return_vnf_package_vnfd() |
|
|
|
updates = {'vnfd_id': uuidsentinel.vnfd_id} |
|
mock_vnf_instance_create.return_value =\ |
|
fakes.return_vnf_instance_model(**updates) |
|
|
|
body = {'vnfdId': uuidsentinel.vnfd_id} |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
req.environ['tacker.context'] = self.context |
|
|
|
# Call Create API |
|
resp = req.get_response(self.app) |
|
self.assertEqual(http_client.CREATED, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(sync_resource.SyncVnfPackage, 'create_package') |
|
@mock.patch.object(nfvo_client.VnfPackageRequest, "index") |
|
@mock.patch.object(objects.vnf_instance, '_vnf_instance_create') |
|
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd, 'get_by_id') |
|
def test_create_vnf_package_vnfd_not_found( |
|
self, mock_get_by_id_package_vnfd, |
|
mock_vnf_instance_create, |
|
mock_index, mock_create_pkg, |
|
mock_get_service_plugins): |
|
mock_get_by_id_package_vnfd.side_effect =\ |
|
exceptions.VnfPackageVnfdNotFound |
|
|
|
mock_response = mock.MagicMock() |
|
mock_response.ok = True |
|
mock_response.json = mock.MagicMock() |
|
mock_response.json.return_value = ['aaa', 'bbb', 'ccc'] |
|
|
|
mock_index.return_value = mock_response |
|
mock_create_pkg.return_value = None |
|
|
|
updates = {'vnfd_id': uuidsentinel.vnfd_id} |
|
mock_vnf_instance_create.return_value =\ |
|
fakes.return_vnf_instance_model(**updates) |
|
|
|
body = {'vnfdId': uuidsentinel.vnfd_id} |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Create API |
|
resp = req.get_response(self.app) |
|
self.assertEqual(http_client.INTERNAL_SERVER_ERROR, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(nfvo_client.VnfPackageRequest, "index") |
|
@mock.patch.object(objects.vnf_instance, '_vnf_instance_create') |
|
@mock.patch.object(objects.vnf_package_vnfd.VnfPackageVnfd, 'get_by_id') |
|
def test_create_non_vnf_package_info( |
|
self, mock_get_by_id_package_vnfd, |
|
mock_vnf_instance_create, |
|
mock_index, mock_get_service_plugins): |
|
mock_get_by_id_package_vnfd.side_effect =\ |
|
exceptions.VnfPackageVnfdNotFound |
|
|
|
mock_response = mock.MagicMock() |
|
mock_response.ok = False |
|
mock_response.json = mock.MagicMock() |
|
mock_response.json.return_value = {} |
|
|
|
mock_index.return_value = mock_response |
|
|
|
updates = {'vnfd_id': uuidsentinel.vnfd_id} |
|
mock_vnf_instance_create.return_value =\ |
|
fakes.return_vnf_instance_model(**updates) |
|
|
|
body = {'vnfdId': uuidsentinel.vnfd_id} |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Create API |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_create_without_vnfd_id(self, mock_get_service_plugins): |
|
body = {"vnfInstanceName": "SampleVnfInstance", |
|
"metadata": {"key": "value"}} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data('PATCH', 'PUT', 'HEAD', 'DELETE') |
|
def test_create_not_allowed_http_method(self, method, |
|
mock_get_service_plugins): |
|
"""Wrong HTTP method""" |
|
body = {"vnfdId": uuidsentinel.vnfd_id} |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = method |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.METHOD_NOT_ALLOWED, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data({'name': "A" * 256, |
|
'description': "VNF Description", |
|
'meta': {"key": "value"}}, |
|
{'name': 'Fake-VNF', |
|
'description': "A" * 1025, |
|
'meta': {"key": "value"}}, |
|
{'name': 'Fake-VNF', |
|
'description': "VNF Description", |
|
'meta': {"key": "v" * 256}}) |
|
def test_create_max_length_exceeded_for_vnf_name_and_description( |
|
self, values, mock_get_service_plugins): |
|
name = values['name'] |
|
meta = values['meta'] |
|
description = values['description'] |
|
# vnf instance_name and description with length greater than max |
|
# length defined |
|
body = {"vnfInstanceName": name, |
|
"vnfdId": uuidsentinel.vnfd_id, |
|
"vnfInstanceDescription": description, |
|
'metadata': meta} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfInstance, "save") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "instantiate") |
|
def test_instantiate_with_deployment_flavour( |
|
self, mock_instantiate, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, mock_save, |
|
mock_vnf_instance_get_by_id, mock_get_vim, |
|
mock_get_vnf, mock_insta_notfi_process, |
|
mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "simple"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertTrue('Location' in resp.headers.keys()) |
|
expected_location = (self.expected_location_prefix + |
|
str(mock_insta_notfi_process.return_value)) |
|
self.assertEqual(expected_location, resp.headers['location']) |
|
self.assertEqual(http_client.ACCEPTED, resp.status_code) |
|
mock_instantiate.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
def test_instantiate_with_non_existing_deployment_flavour( |
|
self, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, |
|
mock_vnf_instance_get_by_id, mock_get_vnf, |
|
mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "invalid"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("No flavour with id 'invalid'.", |
|
resp.json['badRequest']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfInstance, "save") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "instantiate") |
|
def test_instantiate_with_instantiation_level( |
|
self, mock_instantiate, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, mock_save, |
|
mock_vnf_instance_get_by_id, mock_get_vim, |
|
mock_get_vnf, mock_insta_notif_process, |
|
mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "simple", |
|
"instantiationLevelId": "instantiation_level_1"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertTrue('Location' in resp.headers.keys()) |
|
expected_location = (self.expected_location_prefix + |
|
str(mock_insta_notif_process.return_value)) |
|
self.assertEqual(expected_location, resp.headers['location']) |
|
self.assertEqual(http_client.ACCEPTED, resp.status_code) |
|
mock_instantiate.assert_called_once() |
|
mock_get_vnf.assert_called_once() |
|
mock_insta_notif_process.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfInstance, "save") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "instantiate") |
|
def test_instantiate_with_no_inst_level_in_flavour( |
|
self, mock_instantiate, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, mock_save, |
|
mock_vnf_instance_get_by_id, mock_get_vim, |
|
mock_get_vnf, mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
vnf_package = fakes.return_vnf_package_with_deployment_flavour() |
|
vnf_package.vnf_deployment_flavours[0].instantiation_levels = None |
|
mock_vnf_package_get_by_id.return_value = vnf_package |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
# No instantiation level in deployment flavour but it's passed in the |
|
# request |
|
body = {"flavourId": "simple", |
|
"instantiationLevelId": "instantiation_level_1"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("No instantiation level with id " |
|
"'instantiation_level_1'.", |
|
resp.json['badRequest']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "instantiate") |
|
def test_instantiate_with_non_existing_instantiation_level( |
|
self, mock_instantiate, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, |
|
mock_vnf_instance_get_by_id, mock_get_vnf, |
|
mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "simple", |
|
"instantiationLevelId": "non-existing"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("No instantiation level with id 'non-existing'.", |
|
resp.json['badRequest']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.VnfLcmController.' |
|
'_notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfInstance, "save") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "instantiate") |
|
def test_instantiate_with_vim_connection( |
|
self, mock_instantiate, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, mock_save, |
|
mock_vnf_instance_get_by_id, mock_get_vim, |
|
mock_get_vnf, mock_insta_notif_process, |
|
mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "simple", |
|
"vimConnectionInfo": [ |
|
{"id": uuidsentinel.vim_connection_id, |
|
"vimId": uuidsentinel.vim_id, |
|
"vimType": 'openstack'} |
|
]} |
|
|
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertTrue('Location' in resp.headers.keys()) |
|
expected_location = (self.expected_location_prefix + |
|
str(mock_insta_notif_process.return_value)) |
|
self.assertEqual(expected_location, resp.headers['location']) |
|
self.assertEqual(http_client.ACCEPTED, resp.status_code) |
|
mock_instantiate.assert_called_once() |
|
mock_get_vnf.assert_called_once() |
|
mock_insta_notif_process.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
def test_instantiate_with_non_existing_vim( |
|
self, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, |
|
mock_vnf_instance_get_by_id, mock_get_vim, |
|
mock_get_vnf, mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vim.side_effect = nfvo.VimNotFoundException |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "simple", |
|
"vimConnectionInfo": [ |
|
{"id": uuidsentinel.vim_connection_id, |
|
"vimId": uuidsentinel.vim_id, |
|
"vimType": 'openstack'} |
|
]} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("VimConnection id is not found: %s" % |
|
uuidsentinel.vim_id, |
|
resp.json['badRequest']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
def test_instantiate_with_non_existing_region_vim( |
|
self, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, |
|
mock_vnf_instance_get_by_id, mock_get_vim, |
|
mock_get_vnf, mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vim.side_effect = nfvo.VimRegionNotFoundException |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "simple", |
|
"vimConnectionInfo": [ |
|
{'id': uuidsentinel.vim_connection_id, |
|
'vimId': uuidsentinel.vim_id, |
|
'vimType': 'openstack', |
|
'accessInfo': {"region": 'region_non_existing'}} |
|
]} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("Region not found for the VimConnection: %s" % |
|
uuidsentinel.vim_id, |
|
resp.json['badRequest']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(vim_client.VimClient, "get_vim") |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id') |
|
@mock.patch.object(objects.VnfPackage, "get_by_id") |
|
def test_instantiate_with_default_vim_not_configured( |
|
self, mock_vnf_package_get_by_id, |
|
mock_vnf_package_vnfd_get_by_id, |
|
mock_vnf_instance_get_by_id, mock_get_vim, |
|
mock_get_vnf, mock_get_service_plugins): |
|
|
|
mock_vnf_instance_get_by_id.return_value =\ |
|
fakes.return_vnf_instance_model() |
|
mock_vnf_package_vnfd_get_by_id.return_value = \ |
|
fakes.return_vnf_package_vnfd() |
|
mock_vnf_package_get_by_id.return_value = \ |
|
fakes.return_vnf_package_with_deployment_flavour() |
|
mock_get_vim.side_effect = nfvo.VimDefaultNotDefined |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf( |
|
vnf_id=mock_vnf_instance_get_by_id.return_value.id, |
|
status='INACTIVE') |
|
|
|
body = {"flavourId": "simple"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("Default VIM is not defined.", |
|
resp.json['badRequest']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
def test_instantiate_incorrect_instantiation_state( |
|
self, mock_vnf_by_id, mock_get_vnf, mock_get_service_plugins): |
|
vnf_instance = fakes.return_vnf_instance_model() |
|
vnf_instance.instantiation_state = 'INSTANTIATED' |
|
mock_vnf_by_id.return_value = vnf_instance |
|
|
|
body = {"flavourId": "simple"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.CONFLICT, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
def test_instantiate_incorrect_task_state( |
|
self, |
|
mock_vnf_by_id, |
|
mock_get_vnf, |
|
mock_get_service_plugins): |
|
vnf_instance = fakes.return_vnf_instance_model( |
|
task_state=fields.VnfInstanceTaskState.INSTANTIATING) |
|
mock_vnf_by_id.return_value = vnf_instance |
|
|
|
body = {"flavourId": "simple"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.CONFLICT, resp.status_code) |
|
expected_msg = ("Vnf instance %s in task_state INSTANTIATING. Cannot " |
|
"instantiate while the vnf instance is in this state.") |
|
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, |
|
resp.json['conflictingRequest']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data({'attribute': 'flavourId', 'value': 123, |
|
'expected_type': 'string'}, |
|
{'attribute': 'flavourId', 'value': True, |
|
'expected_type': 'string'}, |
|
{'attribute': 'instantiationLevelId', 'value': 123, |
|
'expected_type': 'string'}, |
|
{'attribute': 'instantiationLevelId', 'value': True, |
|
'expected_type': 'string'}, |
|
{'attribute': 'additionalParams', 'value': ['val1', 'val2'], |
|
'expected_type': 'object'}, |
|
{'attribute': 'additionalParams', 'value': True, |
|
'expected_type': 'object'}, |
|
{'attribute': 'additionalParams', 'value': 123, |
|
'expected_type': 'object'}, |
|
) |
|
@ddt.unpack |
|
def test_instantiate_with_invalid_request_body( |
|
self, mock_get_service_plugins, attribute, value, expected_type): |
|
body = fakes.get_vnf_instantiation_request_body() |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
|
|
body.update({attribute: value}) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
exception = self.assertRaises( |
|
exceptions.ValidationError, self.controller.instantiate, |
|
req, body=body) |
|
expected_message = \ |
|
("Invalid input for field/attribute {attribute}. Value: {value}. " |
|
"{value} is not of type '{expected_type}'". |
|
format(value=value, attribute=attribute, |
|
expected_type=expected_type)) |
|
|
|
self.assertEqual(expected_message, exception.msg) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_instantiate_without_flavour_id(self, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes({}) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("'flavourId' is a required property", |
|
resp.json['badRequest']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_instantiate_invalid_request_parameter(self, |
|
mock_get_service_plugins): |
|
body = {"flavourId": "simple"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
|
|
# Pass invalid request parameter |
|
body = {"flavourId": "simple"} |
|
body.update({'additional_property': 'test_value'}) |
|
|
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.INTERNAL_SERVER_ERROR, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_instantiate_with_invalid_uuid(self, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % constants.INVALID_UUID) |
|
body = {"flavourId": "simple"} |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
self.assertEqual( |
|
"Can not find requested vnf: %s" % constants.INVALID_UUID, |
|
resp.json['itemNotFound']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_instantiate_with_non_existing_vnf_instance( |
|
self, mock_vnf_by_id, mock_get_vnf, |
|
mock_get_service_plugins): |
|
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound |
|
body = {"flavourId": "simple"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/instantiate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call Instantiate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
self.assertEqual("Can not find requested vnf instance: %s" % |
|
uuidsentinel.vnf_instance_id, |
|
resp.json['itemNotFound']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH', 'GET') |
|
def test_instantiate_invalid_http_method(self, method, |
|
mock_get_service_plugins): |
|
# Wrong HTTP method |
|
body = fakes.get_vnf_instantiation_request_body() |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/29c770a3-02bc-4dfc-b4be-eb173ac00567/instantiate') |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = method |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.METHOD_NOT_ALLOWED, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
def test_show_vnf_not_instantiated(self, mock_vnf_by_id, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.instance_id) |
|
mock_vnf_by_id.return_value = fakes.return_vnf_instance_model() |
|
expected_result = fakes.fake_vnf_instance_response() |
|
res_dict = self.controller.show(req, uuidsentinel.instance_id) |
|
self.assertEqual(expected_result, res_dict) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_show_vnf_instantiated(self, mock_vnf_by_id, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.instance_id) |
|
mock_vnf_by_id.return_value = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
expected_result = fakes.fake_vnf_instance_response( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
res_dict = self.controller.show(req, uuidsentinel.instance_id) |
|
self.assertEqual(expected_result, res_dict) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_show_vnf_instantiated_with_vim_info( |
|
self, mock_vnf_by_id, mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.instance_id) |
|
|
|
vim_info = { |
|
"id": "7d24979f-491e-4fa3-8da1-4a374fe28d55", |
|
"vim_id": None, |
|
"vim_type": "ETSINFV.OPENSTACK_KEYSTONE.v_2", |
|
"interface_info": {"endpoint": "http://127.0.0.1/identity"}, |
|
"access_info": { |
|
"username": "nfv_user", |
|
"region": "RegionOne", |
|
"password": "devstack", |
|
"tenant": "85d12da99f8246dfae350dbc7334a473", |
|
} |
|
} |
|
|
|
vim_connection_info = objects.VimConnectionInfo( |
|
id=vim_info['id'], vim_id=vim_info['vim_id'], |
|
vim_type=vim_info['vim_type'], |
|
access_info=vim_info['access_info'], |
|
interface_info=vim_info['interface_info']) |
|
|
|
mock_vnf_by_id.return_value = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED, |
|
vim_connection_info=[vim_connection_info]) |
|
|
|
vim_info = common_utils.convert_snakecase_to_camelcase(vim_info) |
|
expected_result = fakes.fake_vnf_instance_response( |
|
fields.VnfInstanceState.INSTANTIATED, |
|
vimConnectionInfo=[vim_info]) |
|
|
|
res_dict = self.controller.show(req, uuidsentinel.instance_id) |
|
self.assertEqual(expected_result, res_dict) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
def test_show_with_non_existing_vnf_instance(self, mock_vnf_by_id, |
|
mock_get_service_plugins): |
|
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id) |
|
|
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
self.assertEqual("Can not find requested vnf instance: %s" % |
|
uuidsentinel.vnf_instance_id, |
|
resp.json['itemNotFound']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_show_with_invalid_uuid(self, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % constants.INVALID_UUID) |
|
|
|
resp = req.get_response(self.app) |
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
self.assertEqual("Can not find requested vnf instance: %s" % |
|
constants.INVALID_UUID, |
|
resp.json['itemNotFound']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data('HEAD', 'PUT', 'POST') |
|
def test_show_invalid_http_method(self, http_method, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % constants.UUID) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = http_method |
|
|
|
resp = req.get_response(self.app) |
|
self.assertEqual(http_client.METHOD_NOT_ALLOWED, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
@mock.patch.object(objects.VnfInstance, "save") |
|
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "terminate") |
|
@ddt.data({'terminationType': 'FORCEFUL'}, |
|
{'terminationType': 'GRACEFUL'}, |
|
{'terminationType': 'GRACEFUL', |
|
'gracefulTerminationTimeout': 10}) |
|
def test_terminate(self, body, mock_terminate, mock_save, |
|
mock_get_by_id, mock_get_vnf, |
|
mock_notification_process, |
|
mock_get_service_plugins): |
|
vnf_instance_obj = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
mock_get_by_id.return_value = vnf_instance_obj |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf(vnf_id=vnf_instance_obj.id, status='ACTIVE') |
|
|
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
expected_location = (self.expected_location_prefix + |
|
str(mock_notification_process.return_value)) |
|
self.assertEqual(expected_location, resp.headers['location']) |
|
self.assertEqual(http_client.ACCEPTED, resp.status_code) |
|
mock_terminate.assert_called_once() |
|
mock_get_vnf.assert_called_once() |
|
mock_notification_process.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data( |
|
{'attribute': 'terminationType', 'value': "TEST", |
|
'expected_type': 'enum'}, |
|
{'attribute': 'terminationType', 'value': 123, |
|
'expected_type': 'enum'}, |
|
{'attribute': 'terminationType', 'value': True, |
|
'expected_type': 'enum'}, |
|
{'attribute': 'gracefulTerminationTimeout', 'value': True, |
|
'expected_type': 'integer'}, |
|
{'attribute': 'gracefulTerminationTimeout', 'value': "test", |
|
'expected_type': 'integer'} |
|
) |
|
def test_terminate_with_invalid_request_body( |
|
self, values, mock_get_service_plugins): |
|
attribute = values['attribute'] |
|
value = values['value'] |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id) |
|
body = {'terminationType': 'GRACEFUL', |
|
'gracefulTerminationTimeout': 10} |
|
body.update({attribute: value}) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
expected_message = ("Invalid input for field/attribute {attribute}. " |
|
"Value: {value}.". |
|
format(value=value, attribute=attribute)) |
|
|
|
exception = self.assertRaises(exceptions.ValidationError, |
|
self.controller.terminate, |
|
req, constants.UUID, body=body) |
|
self.assertIn(expected_message, exception.msg) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_terminate_missing_termination_type(self, |
|
mock_get_service_plugins): |
|
body = {'gracefulTerminationTimeout': 10} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
# Call terminate API |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
self.assertEqual("'terminationType' is a required property", |
|
resp.json['badRequest']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data('GET', 'HEAD', 'PUT', 'DELETE', 'PATCH') |
|
def test_terminate_invalid_http_method(self, method, |
|
mock_get_service_plugins): |
|
# Wrong HTTP method |
|
body = {'terminationType': 'GRACEFUL', |
|
'gracefulTerminationTimeout': 10} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = method |
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.METHOD_NOT_ALLOWED, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
def test_terminate_non_existing_vnf_instance( |
|
self, mock_vnf_by_id, mock_get_vnf, mock_get_service_plugins): |
|
body = {'terminationType': 'GRACEFUL', |
|
'gracefulTerminationTimeout': 10} |
|
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
self.assertEqual("Can not find requested vnf instance: %s" % |
|
uuidsentinel.vnf_instance_id, |
|
resp.json['itemNotFound']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_terminate_incorrect_task_state( |
|
self, |
|
mock_vnf_by_id, |
|
mock_get_vnf, |
|
mock_get_service_plugins): |
|
vnf_instance = fakes.return_vnf_instance( |
|
instantiated_state=fields.VnfInstanceState.INSTANTIATED, |
|
task_state=fields.VnfInstanceTaskState.TERMINATING) |
|
mock_vnf_by_id.return_value = vnf_instance |
|
|
|
body = {"terminationType": "FORCEFUL"} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/terminate' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.CONFLICT, resp.status_code) |
|
expected_msg = ("Vnf instance %s in task_state TERMINATING. Cannot " |
|
"terminate while the vnf instance is in this state.") |
|
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, |
|
resp.json['conflictingRequest']['message']) |
|
mock_get_vnf.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
@mock.patch.object(objects.VnfInstance, "save") |
|
@mock.patch.object(vnf_lcm_rpc.VNFLcmRPCAPI, "heal") |
|
@ddt.data({'cause': 'healing'}, {}) |
|
def test_heal(self, body, mock_rpc_heal, mock_save, |
|
mock_vnf_by_id, mock_get_vnf, |
|
mock_heal_notif_process, |
|
mock_get_service_plugins): |
|
vnf_instance_obj = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
mock_vnf_by_id.return_value = vnf_instance_obj |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf(vnf_id=vnf_instance_obj.id, status='ACTIVE') |
|
|
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertTrue('Location' in resp.headers.keys()) |
|
expected_location = (self.expected_location_prefix + |
|
str(mock_heal_notif_process.return_value)) |
|
self.assertEqual(expected_location, resp.headers['location']) |
|
self.assertEqual(http_client.ACCEPTED, resp.status_code) |
|
mock_rpc_heal.assert_called_once() |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_heal_cause_max_length_exceeded(self, |
|
mock_get_service_plugins): |
|
body = {'cause': 'A' * 256} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_heal_incorrect_instantiated_state( |
|
self, |
|
mock_vnf_by_id, |
|
mock_get_vnf, |
|
mock_notif, |
|
mock_get_service_plugins): |
|
vnf_instance_obj = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.NOT_INSTANTIATED) |
|
mock_vnf_by_id.return_value = vnf_instance_obj |
|
|
|
body = {} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.CONFLICT, resp.status_code) |
|
expected_msg = ("Vnf instance %s in instantiation_state " |
|
"NOT_INSTANTIATED. Cannot heal while the vnf instance " |
|
"is in this state.") |
|
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, |
|
resp.json['conflictingRequest']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_heal_incorrect_task_state(self, mock_vnf_by_id, mock_get_vnf, |
|
mock_notif, mock_get_service_plugins): |
|
vnf_instance_obj = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED, |
|
task_state=fields.VnfInstanceTaskState.HEALING) |
|
mock_vnf_by_id.return_value = vnf_instance_obj |
|
|
|
body = {} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.CONFLICT, resp.status_code) |
|
expected_msg = ("Vnf instance %s in task_state " |
|
"HEALING. Cannot heal while the vnf instance " |
|
"is in this state.") |
|
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, |
|
resp.json['conflictingRequest']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._notification_process') |
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._get_vnf') |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_heal_with_invalid_vnfc_id( |
|
self, |
|
mock_vnf_by_id, |
|
mock_get_vnf, |
|
mock_notif, |
|
mock_get_service_plugins): |
|
vnf_instance_obj = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
mock_vnf_by_id.return_value = vnf_instance_obj |
|
mock_get_vnf.return_value = \ |
|
self._get_dummy_vnf(vnf_id=vnf_instance_obj.id, status='ACTIVE') |
|
|
|
body = {'vnfcInstanceId': [uuidsentinel.vnfc_instance_id]} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.BAD_REQUEST, resp.status_code) |
|
expected_msg = "Vnfc id %s not present in vnf instance %s" |
|
self.assertEqual(expected_msg % (uuidsentinel.vnfc_instance_id, |
|
uuidsentinel.vnf_instance_id), |
|
resp.json['badRequest']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH', 'GET') |
|
def test_heal_invalid_http_method(self, method, |
|
mock_get_service_plugins): |
|
body = {} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s/heal' % uuidsentinel.vnf_instance_id) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = method |
|
|
|
resp = req.get_response(self.app) |
|
self.assertFalse('Location' in resp.headers.keys()) |
|
self.assertEqual(http_client.METHOD_NOT_ALLOWED, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data({'attribute': 'cause', 'value': 123, |
|
'expected_type': 'string'}, |
|
{'attribute': 'cause', 'value': True, |
|
'expected_type': 'string'}, |
|
{'attribute': 'vnfcInstanceId', 'value': 123, |
|
'expected_type': 'array'}, |
|
{'attribute': 'vnfcInstanceId', 'value': True, |
|
'expected_type': 'array'}, |
|
) |
|
@ddt.unpack |
|
def test_heal_with_invalid_request_body( |
|
self, mock_get_service_plugins, attribute, value, expected_type): |
|
body = {} |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/29c770a3-02bc-4dfc-b4be-eb173ac00567/heal') |
|
body.update({attribute: value}) |
|
req.body = jsonutils.dump_as_bytes(body) |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'POST' |
|
exception = self.assertRaises( |
|
exceptions.ValidationError, self.controller.heal, |
|
req, body=body) |
|
expected_message = \ |
|
("Invalid input for field/attribute {attribute}. Value: {value}. " |
|
"{value} is not of type '{expected_type}'". |
|
format(value=value, attribute=attribute, |
|
expected_type=expected_type)) |
|
|
|
self.assertEqual(expected_message, exception.msg) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
def test_index(self, mock_vnf_list): |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
vnf_instance_1 = fakes.return_vnf_instance() |
|
vnf_instance_2 = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
|
|
mock_vnf_list.return_value = [vnf_instance_1, vnf_instance_2] |
|
resp = self.controller.index(req) |
|
expected_result = [fakes.fake_vnf_instance_response(), |
|
fakes.fake_vnf_instance_response( |
|
fields.VnfInstanceState.INSTANTIATED)] |
|
self.assertEqual(expected_result, resp) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
def test_index_empty_response(self, mock_vnf_list): |
|
req = fake_request.HTTPRequest.blank('/vnf_instances') |
|
mock_vnf_list.return_value = [] |
|
resp = self.controller.index(req) |
|
self.assertEqual([], resp) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@ddt.data('HEAD', 'PUT', 'DELETE', 'PATCH') |
|
def test_index_invalid_http_method(self, method, |
|
mock_get_service_plugins): |
|
# Wrong HTTP method |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances') |
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = method |
|
resp = req.get_response(self.app) |
|
self.assertEqual(http_client.METHOD_NOT_ALLOWED, resp.status_code) |
|
|
|
@mock.patch('tacker.api.vnflcm.v1.controller.' |
|
'VnfLcmController._delete') |
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.vnf_instance, "_vnf_instance_get_by_id") |
|
@mock.patch.object(objects.vnf_instance, '_destroy_vnf_instance') |
|
def test_delete(self, mock_destroy_vnf_instance, mock_vnf_by_id, |
|
mock_get_service_plugins, mock_private_delete): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id) |
|
req.method = 'DELETE' |
|
mock_vnf_by_id.return_value = fakes.return_vnf_instance() |
|
req.headers['Content-Type'] = 'application/json' |
|
|
|
# Call delete API |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.NO_CONTENT, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_delete_with_non_existing_vnf_instance(self, mock_vnf_by_id, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id) |
|
req.method = 'DELETE' |
|
|
|
mock_vnf_by_id.side_effect = exceptions.VnfInstanceNotFound |
|
|
|
# Call delete API |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
self.assertEqual("Can not find requested vnf instance: %s" % |
|
uuidsentinel.vnf_instance_id, |
|
resp.json['itemNotFound']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
def test_delete_with_invalid_uuid(self, mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % constants.INVALID_UUID) |
|
req.method = 'DELETE' |
|
|
|
# Call delete API |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
self.assertEqual("Can not find requested vnf instance: %s" % |
|
constants.INVALID_UUID, |
|
resp.json['itemNotFound']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_delete_with_incorrect_instantiation_state( |
|
self, mock_vnf_by_id, mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id) |
|
req.method = 'DELETE' |
|
|
|
vnf_instance = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
mock_vnf_by_id.return_value = vnf_instance |
|
|
|
# Call delete API |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.CONFLICT, resp.status_code) |
|
expected_msg = ("Vnf instance %s in instantiation_state " |
|
"INSTANTIATED. Cannot delete while the vnf instance " |
|
"is in this state.") |
|
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, |
|
resp.json['conflictingRequest']['message']) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VnfInstance, "get_by_id") |
|
def test_delete_with_incorrect_task_state(self, mock_vnf_by_id, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_instances/%s' % uuidsentinel.vnf_instance_id) |
|
req.method = 'DELETE' |
|
|
|
vnf_instance = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.NOT_INSTANTIATED, |
|
task_state=fields.VnfInstanceTaskState.ERROR) |
|
mock_vnf_by_id.return_value = vnf_instance |
|
|
|
# Call delete API |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.CONFLICT, resp.status_code) |
|
expected_msg = ("Vnf instance %s in task_state ERROR. " |
|
"Cannot delete while the vnf instance " |
|
"is in this state.") |
|
self.assertEqual(expected_msg % uuidsentinel.vnf_instance_id, |
|
resp.json['conflictingRequest']['message']) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
@ddt.data( |
|
{'filter': "(eq,vnfInstanceName,'dummy_name')"}, |
|
{'filter': "(in,vnfInstanceName,'dummy_name')"}, |
|
{'filter': "(cont,vnfInstanceName,'dummy_name')"}, |
|
{'filter': "(neq,vnfInstanceName,'dummy_name')"}, |
|
{'filter': "(nin,vnfInstanceName,'dummy_name')"}, |
|
{'filter': "(ncont,vnfInstanceName,'dummy_name')"}, |
|
{'filter': "(gt,vnfdVersion, 1)"}, |
|
{'filter': "(gte,vnfdVersion, 1)"}, |
|
{'filter': "(lt,vnfdVersion, 1)"}, |
|
{'filter': "(lte,vnfdVersion, 1)"}, |
|
) |
|
def test_index_filter_operator(self, filter_params, mock_vnf_list): |
|
"""Tests all supported operators in filter expression.""" |
|
query = urllib.parse.urlencode(filter_params) |
|
|
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
|
|
vnf_instance_1 = fakes.return_vnf_instance() |
|
vnf_instance_2 = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
|
|
mock_vnf_list.return_value = [vnf_instance_1, vnf_instance_2] |
|
res_dict = self.controller.index(req) |
|
|
|
expected_result = [fakes.fake_vnf_instance_response(), |
|
fakes.fake_vnf_instance_response( |
|
fields.VnfInstanceState.INSTANTIATED)] |
|
self.assertEqual(expected_result, res_dict) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
def test_index_filter_combination(self, mock_vnf_list): |
|
"""Test multiple filter parameters separated by semicolon.""" |
|
params = { |
|
'filter': "(eq,vnfInstanceName,'dummy_name');" |
|
"(eq,vnfInstanceDescription,'dummy_desc')"} |
|
|
|
query = urllib.parse.urlencode(params) |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
|
|
vnf_instance_1 = fakes.return_vnf_instance() |
|
vnf_instance_2 = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
|
|
mock_vnf_list.return_value = [vnf_instance_1, vnf_instance_2] |
|
res_dict = self.controller.index(req) |
|
|
|
expected_result = [fakes.fake_vnf_instance_response(), |
|
fakes.fake_vnf_instance_response( |
|
fields.VnfInstanceState.INSTANTIATED)] |
|
self.assertEqual(expected_result, res_dict) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
@ddt.data( |
|
{'filter': "(eq,vnfInstanceName,dummy_value)"}, |
|
{'filter': "(eq,vnfInstanceDescription,dummy value)"}, |
|
{'filter': "(eq,instantiationState,'NOT_INSTANTIATED')"}, |
|
{'filter': "(eq,taskState,'ACTIVE')"}, |
|
{'filter': "(eq,vnfdId,'dummy_vnfd_id')"}, |
|
{'filter': "(eq,vnfProvider,'''dummy ''hi'' value''')"}, |
|
{'filter': "(eq,vnfProductName,'dummy_product_name')"}, |
|
{'filter': "(eq,vnfSoftwareVersion,'1.0')"}, |
|
{'filter': "(eq,vnfdVersion,'dummy_vnfd_version')"}, |
|
{'filter': "(eq,tenantId,'dummy_tenant_id')"}, |
|
{'filter': "(eq,vnfPkgId,'dummy_pkg_id')"}, |
|
{'filter': "(eq,vimConnectionInfo/accessInfo/region,'dummy_id')"}, |
|
{'filter': "(eq,instantiatedInfo/flavourId,'dummy_flavour')"}, |
|
{'filter': "(eq,instantiatedInfo/vnfInstanceId,'dummy_vnf_id')"}, |
|
{'filter': "(eq,instantiatedInfo/vnfState,'ACTIVE')"}, |
|
{'filter': "(eq,instantiatedInfo/instanceId,'dummy_vnf_id')"}, |
|
{'filter': |
|
"(eq,instantiatedInfo/instantiationLevelId,'dummy_level_id')"}, |
|
{'filter': "(eq,instantiatedInfo/extCpInfo/id,'dummy_id')"}, |
|
{'filter': "(eq,instantiatedInfo/extVirtualLinkInfo/name,'dummy')"}, |
|
{'filter': |
|
"(eq,instantiatedInfo/extManagedVirtualLinkInfo/id,'dummy_id')"}, |
|
{'filter': "(eq,instantiatedInfo/vnfcResourceInfo/vduId,'dummy_id')"}, |
|
{'filter': |
|
"(eq,instantiatedInfo/vnfVirtualLinkResourceInfo/" |
|
"vnfVirtualLinkDescId,'dummy_id')"}, |
|
{'filter': |
|
"(eq,instantiatedInfo/virtualStorageResourceInfo/" |
|
"virtualStorageDescId,'dummy_id')"}, |
|
{'filter': "(eq,instantiatedInfo/additionalParams/error,'dummy')"}, |
|
) |
|
def test_index_filter_attributes(self, filter_params, |
|
mock_vnf_list): |
|
"""Test various attributes supported for filter parameter.""" |
|
query = urllib.parse.urlencode(filter_params) |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
|
|
vnf_instance_1 = fakes.return_vnf_instance() |
|
vnf_instance_2 = fakes.return_vnf_instance( |
|
fields.VnfInstanceState.INSTANTIATED) |
|
|
|
mock_vnf_list.return_value = [vnf_instance_1, vnf_instance_2] |
|
res_dict = self.controller.index(req) |
|
|
|
expected_result = [fakes.fake_vnf_instance_response(), |
|
fakes.fake_vnf_instance_response( |
|
fields.VnfInstanceState.INSTANTIATED)] |
|
self.assertEqual(expected_result, res_dict) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
@ddt.data( |
|
{'filter': "(eq,vnfInstanceName,value"}, |
|
{'filter': "eq,vnfInstanceName,value)"}, |
|
{'filter': "(eq,vnfInstanceName,value);"}, |
|
{'filter': "(eq , vnfInstanceName ,value)"}, |
|
) |
|
def test_index_filter_invalid_expression(self, filter_params, |
|
mock_vnf_list): |
|
"""Test invalid filter expression.""" |
|
query = urllib.parse.urlencode(filter_params) |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
|
|
self.assertRaises(exceptions.ValidationError, |
|
self.controller.index, req) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
@ddt.data( |
|
{'filter': "(eq,vnfInstanceName,singl'quote)"}, |
|
{'filter': "(eq,vnfInstanceName,three''' quotes)"}, |
|
{'filter': "(eq,vnfInstanceName,round ) bracket)"}, |
|
{'filter': "(eq,vnfInstanceName,'dummy 'hi' value')"}, |
|
{'filter': "(eq,vnfInstanceName,'dummy's value')"}, |
|
{'filter': "(eq,vnfInstanceName,'three ''' quotes')"}, |
|
) |
|
def test_index_filter_invalid_string_values(self, filter_params, |
|
mock_vnf_list): |
|
"""Test invalid string values as per ETSI NFV SOL013 5.2.2.""" |
|
query = urllib.parse.urlencode(filter_params) |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
self.assertRaises(exceptions.ValidationError, |
|
self.controller.index, req) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
@ddt.data( |
|
{'filter': '(eq,vnfdId,value1,value2)'}, |
|
{'filter': '(fake,vnfdId,dummy_vnfd_id)'}, |
|
{'filter': '(,vnfdId,dummy_vnfd_id)'}, |
|
) |
|
def test_index_filter_invalid_operator(self, filter_params, |
|
mock_vnf_list): |
|
"""Test invalid operator in filter expression.""" |
|
query = urllib.parse.urlencode(filter_params) |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
self.assertRaises(exceptions.ValidationError, |
|
self.controller.index, req) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
@ddt.data( |
|
{'filter': '(eq,fakeattr,fakevalue)'}, |
|
{'filter': '(eq,,fakevalue)'}, |
|
) |
|
def test_index_filter_invalid_attribute(self, filter_params, |
|
mock_vnf_list): |
|
"""Test invalid attribute in filter expression.""" |
|
query = urllib.parse.urlencode(filter_params) |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
self.assertRaises(exceptions.ValidationError, |
|
self.controller.index, req) |
|
|
|
@mock.patch.object(objects.VnfInstanceList, "get_by_filters") |
|
@ddt.data( |
|
{'filter': '(eq,data/size,fake_value)'}, |
|
{'filter': '(gt,data/createdAt,fake_value)'}, |
|
{'filter': '(eq,data/minDisk,fake_value)'}, |
|
{'filter': '(eq,data/minRam,fake_value)'}, |
|
) |
|
def test_index_filter_invalid_value_type(self, filter_params, |
|
mock_vnf_list): |
|
"""Test values which doesn't match with attribute data type.""" |
|
query = urllib.parse.urlencode(filter_params) |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnflcm/v1/vnf_instances?' + query) |
|
self.assertRaises(exceptions.ValidationError, |
|
self.controller.index, req) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id") |
|
def test_show_lcm_op_occs(self, mock_get_by_id, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnf_lcm_op_occs/%s' % constants.UUID) |
|
mock_get_by_id.return_value = fakes.return_vnf_lcm_opoccs_obj() |
|
expected_result = fakes.VNFLCMOPOCC_RESPONSE |
|
res_dict = self.controller.show_lcm_op_occs(req, constants.UUID) |
|
self.assertEqual(expected_result, res_dict) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VnfLcmOpOcc, "get_by_id") |
|
def test_show_lcm_op_occs_not_found(self, mock_get_by_id, |
|
mock_get_service_plugins): |
|
req = fake_request.HTTPRequest.blank( |
|
'/vnfpkgm/v1/vnf_packages/%s' % constants.UUID) |
|
mock_get_by_id.side_effect = exceptions.NotFound() |
|
|
|
req.headers['Content-Type'] = 'application/json' |
|
req.method = 'GET' |
|
resp = req.get_response(self.app) |
|
|
|
self.assertEqual(http_client.NOT_FOUND, resp.status_code) |
|
|
|
@mock.patch.object(TackerManager, 'get_service_plugins', |
|
return_value={'VNFM': |
|
test_nfvo_plugin.FakeVNFMPlugin()}) |
|
@mock.patch.object(objects.VNF, "vnf_index_list") |
|
@mock.patch.object(objects.VnfInstanceList, "vnf_instance_list") |
|