OSC support to delete and terminate vnf
Added new commands ``openstack vnflcm delete`` and ``openstack vnflcm terminate``. Blueprint: support-etsi-nfv-specs Change-Id: I72ea99c2149621428a34403504f28f9e9b1a3719
This commit is contained in:
@@ -86,6 +86,8 @@ openstack.tackerclient.v1 =
|
|||||||
vnflcm_create = tackerclient.osc.v1.vnflcm.vnflcm:CreateVnfLcm
|
vnflcm_create = tackerclient.osc.v1.vnflcm.vnflcm:CreateVnfLcm
|
||||||
vnflcm_show = tackerclient.osc.v1.vnflcm.vnflcm:ShowVnfLcm
|
vnflcm_show = tackerclient.osc.v1.vnflcm.vnflcm:ShowVnfLcm
|
||||||
vnflcm_instantiate = tackerclient.osc.v1.vnflcm.vnflcm:InstantiateVnfLcm
|
vnflcm_instantiate = tackerclient.osc.v1.vnflcm.vnflcm:InstantiateVnfLcm
|
||||||
|
vnflcm_terminate = tackerclient.osc.v1.vnflcm.vnflcm:TerminateVnfLcm
|
||||||
|
vnflcm_delete = tackerclient.osc.v1.vnflcm.vnflcm:DeleteVnfLcm
|
||||||
|
|
||||||
[build_releasenotes]
|
[build_releasenotes]
|
||||||
all_files = 1
|
all_files = 1
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
from osc_lib.cli import format_columns
|
from osc_lib.cli import format_columns
|
||||||
from osc_lib.command import command
|
from osc_lib.command import command
|
||||||
@@ -34,6 +35,12 @@ _mixed_case_fields = ('vnfInstanceName', 'vnfInstanceDescription', 'vnfdId',
|
|||||||
|
|
||||||
_VNF_INSTANCE = 'vnf_instance'
|
_VNF_INSTANCE = 'vnf_instance'
|
||||||
|
|
||||||
|
VNF_INSTANCE_TERMINATION_TIMEOUT = 300
|
||||||
|
|
||||||
|
EXTRA_WAITING_TIME = 10
|
||||||
|
|
||||||
|
SLEEP_TIME = 1
|
||||||
|
|
||||||
|
|
||||||
def _get_columns(vnflcm_obj, action=None):
|
def _get_columns(vnflcm_obj, action=None):
|
||||||
column_map = {
|
column_map = {
|
||||||
@@ -186,3 +193,143 @@ class InstantiateVnfLcm(command.Command):
|
|||||||
if not result:
|
if not result:
|
||||||
print((_('Instantiate request for VNF Instance %(id)s has been'
|
print((_('Instantiate request for VNF Instance %(id)s has been'
|
||||||
' accepted.') % {'id': parsed_args.vnf_instance}))
|
' accepted.') % {'id': parsed_args.vnf_instance}))
|
||||||
|
|
||||||
|
|
||||||
|
class TerminateVnfLcm(command.Command):
|
||||||
|
_description = _("Terminate a VNF instance")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(TerminateVnfLcm, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
_VNF_INSTANCE,
|
||||||
|
metavar="<vnf-instance>",
|
||||||
|
help=_("VNF instance ID to terminate"))
|
||||||
|
parser.add_argument(
|
||||||
|
"--termination-type",
|
||||||
|
default='GRACEFUL',
|
||||||
|
metavar="<termination-type>",
|
||||||
|
choices=['GRACEFUL', 'FORCEFUL'],
|
||||||
|
help=_("Termination type can be 'GRACEFUL' or 'FORCEFUL'. "
|
||||||
|
"Default is 'GRACEFUL'"))
|
||||||
|
parser.add_argument(
|
||||||
|
'--graceful-termination-timeout',
|
||||||
|
metavar="<graceful-termination-timeout>",
|
||||||
|
type=int,
|
||||||
|
help=_('This attribute is only applicable in case of graceful '
|
||||||
|
'termination. It defines the time to wait for the VNF to be'
|
||||||
|
' taken out of service before shutting down the VNF and '
|
||||||
|
'releasing the resources. The unit is seconds.'))
|
||||||
|
parser.add_argument(
|
||||||
|
'--D',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help=_("Delete VNF Instance subsequently after it's termination"),
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def args2body(self, parsed_args):
|
||||||
|
body = {}
|
||||||
|
body['terminationType'] = parsed_args.termination_type
|
||||||
|
|
||||||
|
if parsed_args.graceful_termination_timeout:
|
||||||
|
if parsed_args.termination_type == 'FORCEFUL':
|
||||||
|
exceptions.InvalidInput('--graceful-termination-timeout'
|
||||||
|
' argument is invalid for "FORCEFUL"'
|
||||||
|
' termination')
|
||||||
|
body['gracefulTerminationTimeout'] = parsed_args.\
|
||||||
|
graceful_termination_timeout
|
||||||
|
|
||||||
|
return body
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
client = self.app.client_manager.tackerclient
|
||||||
|
result = client.terminate_vnf_instance(parsed_args.vnf_instance,
|
||||||
|
self.args2body(parsed_args))
|
||||||
|
if not result:
|
||||||
|
print(_("Terminate request for VNF Instance '%(id)s' has been"
|
||||||
|
" accepted.") % {'id': parsed_args.vnf_instance})
|
||||||
|
if parsed_args.D:
|
||||||
|
print(_("Waiting for vnf instance to be terminated before "
|
||||||
|
"deleting"))
|
||||||
|
|
||||||
|
self._wait_until_vnf_is_terminated(
|
||||||
|
client, parsed_args.vnf_instance,
|
||||||
|
graceful_timeout=parsed_args.graceful_termination_timeout)
|
||||||
|
|
||||||
|
result = client.delete_vnf_instance(parsed_args.vnf_instance)
|
||||||
|
if not result:
|
||||||
|
print(_("VNF Instance '%(id)s' deleted successfully") %
|
||||||
|
{'id': parsed_args.vnf_instance})
|
||||||
|
|
||||||
|
def _wait_until_vnf_is_terminated(self, client, vnf_instance_id,
|
||||||
|
graceful_timeout=None):
|
||||||
|
# wait until vnf instance 'instantiationState' is set to
|
||||||
|
# 'NOT_INSTANTIATED'
|
||||||
|
if graceful_timeout:
|
||||||
|
# If graceful_termination_timeout is provided,
|
||||||
|
# terminate vnf will start after this timeout period.
|
||||||
|
# Hence, it should wait for extra time of 10 seconds
|
||||||
|
# after this graceful_termination_timeout period.
|
||||||
|
timeout = graceful_timeout + EXTRA_WAITING_TIME
|
||||||
|
else:
|
||||||
|
timeout = VNF_INSTANCE_TERMINATION_TIMEOUT
|
||||||
|
|
||||||
|
start_time = int(time.time())
|
||||||
|
while True:
|
||||||
|
vnf_instance = client.show_vnf_instance(vnf_instance_id)
|
||||||
|
if vnf_instance['instantiationState'] == 'NOT_INSTANTIATED':
|
||||||
|
break
|
||||||
|
|
||||||
|
if ((int(time.time()) - start_time) > timeout):
|
||||||
|
msg = _("Couldn't verify vnf instance is terminated within "
|
||||||
|
"'%(timeout)s' seconds. Unable to delete vnf instance "
|
||||||
|
"%(id)s")
|
||||||
|
raise exceptions.CommandError(msg % {'timeout': timeout,
|
||||||
|
'id': vnf_instance_id})
|
||||||
|
time.sleep(SLEEP_TIME)
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteVnfLcm(command.Command):
|
||||||
|
"""Vnf lcm delete
|
||||||
|
|
||||||
|
DeleteVnfLcm class supports bulk deletion of vnf instances, and error
|
||||||
|
handling.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_description = _("Delete VNF Instance(s)")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(DeleteVnfLcm, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'vnf_instances',
|
||||||
|
metavar="<vnf-instance>",
|
||||||
|
nargs="+",
|
||||||
|
help=_("VNF instance ID(s) to delete"))
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
error_count = 0
|
||||||
|
client = self.app.client_manager.tackerclient
|
||||||
|
vnf_instances = parsed_args.vnf_instances
|
||||||
|
for vnf_instance in vnf_instances:
|
||||||
|
try:
|
||||||
|
client.delete_vnf_instance(vnf_instance)
|
||||||
|
except Exception as e:
|
||||||
|
error_count += 1
|
||||||
|
LOG.error(_("Failed to delete vnf instance with "
|
||||||
|
"ID '%(vnf)s': %(e)s"),
|
||||||
|
{'vnf': vnf_instance, 'e': e})
|
||||||
|
|
||||||
|
total = len(vnf_instances)
|
||||||
|
if (error_count > 0):
|
||||||
|
msg = (_("Failed to delete %(error_count)s of %(total)s "
|
||||||
|
"vnf instances.") % {'error_count': error_count,
|
||||||
|
'total': total})
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
|
else:
|
||||||
|
if total > 1:
|
||||||
|
print(_('All specified vnf instances are deleted '
|
||||||
|
'successfully'))
|
||||||
|
else:
|
||||||
|
print(_("Vnf instance '%s' deleted "
|
||||||
|
"successfully") % vnf_instances[0])
|
||||||
|
@@ -13,13 +13,14 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import ddt
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
import mock
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import ddt
|
||||||
|
import mock
|
||||||
from oslo_utils.fixture import uuidsentinel
|
from oslo_utils.fixture import uuidsentinel
|
||||||
|
import six
|
||||||
|
|
||||||
from tackerclient.common import exceptions
|
from tackerclient.common import exceptions
|
||||||
from tackerclient.osc.v1.vnflcm import vnflcm
|
from tackerclient.osc.v1.vnflcm import vnflcm
|
||||||
@@ -237,3 +238,219 @@ class TestInstantiateVnfLcm(TestVnfLcm):
|
|||||||
|
|
||||||
expected_msg = "Failed to load parameter file."
|
expected_msg = "Failed to load parameter file."
|
||||||
self.assertIn(expected_msg, ex.message)
|
self.assertIn(expected_msg, ex.message)
|
||||||
|
|
||||||
|
|
||||||
|
@ddt.ddt
|
||||||
|
class TestTerminateVnfLcm(TestVnfLcm):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestTerminateVnfLcm, self).setUp()
|
||||||
|
self.terminate_vnf_instance = vnflcm.TerminateVnfLcm(
|
||||||
|
self.app, self.app_args, cmd_name='vnflcm terminate')
|
||||||
|
|
||||||
|
@ddt.data({'termination_type': 'GRACEFUL', 'delete_vnf': True},
|
||||||
|
{'termination_type': 'FORCEFUL', 'delete_vnf': False})
|
||||||
|
@ddt.unpack
|
||||||
|
def test_take_action(self, termination_type, delete_vnf):
|
||||||
|
# argument 'delete_vnf' decides deletion of vnf instance post
|
||||||
|
# termination.
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
arglist = ['--termination-type', termination_type, vnf_instance['id']]
|
||||||
|
|
||||||
|
verifylist = [('termination_type', termination_type),
|
||||||
|
('vnf_instance', vnf_instance['id'])]
|
||||||
|
|
||||||
|
if delete_vnf:
|
||||||
|
arglist.extend(['--D'])
|
||||||
|
verifylist.extend([('D', True)])
|
||||||
|
|
||||||
|
if termination_type == 'GRACEFUL':
|
||||||
|
arglist.extend(['--graceful-termination-timeout', '60'])
|
||||||
|
verifylist.append(('graceful_termination_timeout', 60))
|
||||||
|
parsed_args = self.check_parser(self.terminate_vnf_instance, arglist,
|
||||||
|
verifylist)
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
vnf_instance['id'], 'terminate')
|
||||||
|
|
||||||
|
with mock.patch.object(proxy_client.ClientBase,
|
||||||
|
'_handle_fault_response') as m:
|
||||||
|
self.requests_mock.register_uri('POST', url, json={},
|
||||||
|
headers=self.header)
|
||||||
|
if delete_vnf:
|
||||||
|
self.requests_mock.register_uri(
|
||||||
|
'GET', os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
vnf_instance['id']),
|
||||||
|
json=vnf_instance, headers=self.header)
|
||||||
|
self.requests_mock.register_uri(
|
||||||
|
'DELETE', os.path.join(
|
||||||
|
self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
vnf_instance['id']), json={}, headers=self.header)
|
||||||
|
|
||||||
|
sys.stdout = buffer = StringIO()
|
||||||
|
result = self.terminate_vnf_instance.take_action(parsed_args)
|
||||||
|
actual_message = buffer.getvalue().strip()
|
||||||
|
|
||||||
|
expected_message = ("Terminate request for VNF Instance '%s'"
|
||||||
|
" has been accepted.") % vnf_instance['id']
|
||||||
|
self.assertIn(expected_message, actual_message)
|
||||||
|
|
||||||
|
if delete_vnf:
|
||||||
|
expected_message = ("VNF Instance '%s' deleted successfully"
|
||||||
|
% vnf_instance['id'])
|
||||||
|
self.assertIn(expected_message, actual_message)
|
||||||
|
|
||||||
|
self.assertIsNone(result)
|
||||||
|
self.assertNotCalled(m)
|
||||||
|
|
||||||
|
def test_take_action_terminate_and_delete_wait_failed(self):
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
termination_type = 'GRACEFUL'
|
||||||
|
arglist = ['--termination-type', termination_type, '--D',
|
||||||
|
'--graceful-termination-timeout', '5', vnf_instance['id']]
|
||||||
|
|
||||||
|
verifylist = [('termination_type', termination_type), ('D', True),
|
||||||
|
('graceful_termination_timeout', 5),
|
||||||
|
('vnf_instance', vnf_instance['id'])]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.terminate_vnf_instance, arglist,
|
||||||
|
verifylist)
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
vnf_instance['id'], 'terminate')
|
||||||
|
|
||||||
|
self.requests_mock.register_uri('POST', url, json={},
|
||||||
|
headers=self.header)
|
||||||
|
# set the instantiateState to "INSTANTIATED", so that the
|
||||||
|
# _wait_until_vnf_is_terminated will fail
|
||||||
|
vnf_instance['instantiationState'] = 'INSTANTIATED'
|
||||||
|
|
||||||
|
self.requests_mock.register_uri(
|
||||||
|
'GET', os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
vnf_instance['id']),
|
||||||
|
json=vnf_instance, headers=self.header)
|
||||||
|
|
||||||
|
sys.stdout = buffer = StringIO()
|
||||||
|
with mock.patch.object(self.app.client_manager.tackerclient,
|
||||||
|
'delete_vnf_instance') as mock_delete:
|
||||||
|
result = self.assertRaises(
|
||||||
|
exceptions.CommandError,
|
||||||
|
self.terminate_vnf_instance.take_action, parsed_args)
|
||||||
|
|
||||||
|
actual_message = buffer.getvalue().strip()
|
||||||
|
|
||||||
|
# Terminate vnf instance verification
|
||||||
|
expected_message = ("Terminate request for VNF Instance '%s'"
|
||||||
|
" has been accepted.") % vnf_instance['id']
|
||||||
|
self.assertIn(expected_message, actual_message)
|
||||||
|
|
||||||
|
# Verify it fails to wait for termination before delete
|
||||||
|
expected_message = ("Couldn't verify vnf instance is terminated "
|
||||||
|
"within '%(timeout)s' seconds. Unable to "
|
||||||
|
"delete vnf instance %(id)s"
|
||||||
|
% {'timeout': 15, 'id': vnf_instance['id']})
|
||||||
|
|
||||||
|
self.assertIn(expected_message, six.text_type(result))
|
||||||
|
self.assertNotCalled(mock_delete)
|
||||||
|
|
||||||
|
def test_terminate_no_options(self):
|
||||||
|
self.assertRaises(base.ParserException, self.check_parser,
|
||||||
|
self.terminate_vnf_instance, [], [])
|
||||||
|
|
||||||
|
def test_take_action_vnf_instance_not_found(self):
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
termination_type = 'GRACEFUL'
|
||||||
|
arglist = ['--termination-type', termination_type, '--D',
|
||||||
|
'--graceful-termination-timeout', '5', vnf_instance['id']]
|
||||||
|
|
||||||
|
verifylist = [('termination_type', termination_type), ('D', True),
|
||||||
|
('graceful_termination_timeout', 5),
|
||||||
|
('vnf_instance', vnf_instance['id'])]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.terminate_vnf_instance, arglist,
|
||||||
|
verifylist)
|
||||||
|
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
vnf_instance['id'], 'terminate')
|
||||||
|
self.requests_mock.register_uri('POST', url, headers=self.header,
|
||||||
|
status_code=404, json={})
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.TackerClientException,
|
||||||
|
self.terminate_vnf_instance.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDeleteVnfLcm(TestVnfLcm):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestDeleteVnfLcm, self).setUp()
|
||||||
|
self.delete_vnf_instance = vnflcm.DeleteVnfLcm(
|
||||||
|
self.app, self.app_args, cmd_name='vnflcm delete')
|
||||||
|
|
||||||
|
# Vnf Instance to delete
|
||||||
|
self.vnf_instances = vnflcm_fakes.create_vnf_instances(count=3)
|
||||||
|
|
||||||
|
def _mock_request_url_for_delete(self, vnf_index):
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
self.vnf_instances[vnf_index]['id'])
|
||||||
|
|
||||||
|
json = self.vnf_instances[vnf_index]
|
||||||
|
|
||||||
|
self.requests_mock.register_uri('GET', url, json=json,
|
||||||
|
headers=self.header)
|
||||||
|
self.requests_mock.register_uri('DELETE', url,
|
||||||
|
headers=self.header, json={})
|
||||||
|
|
||||||
|
def test_delete_one_vnf_instance(self):
|
||||||
|
arglist = [self.vnf_instances[0]['id']]
|
||||||
|
verifylist = [('vnf_instances',
|
||||||
|
[self.vnf_instances[0]['id']])]
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(self.delete_vnf_instance, arglist,
|
||||||
|
verifylist)
|
||||||
|
|
||||||
|
self._mock_request_url_for_delete(0)
|
||||||
|
sys.stdout = buffer = StringIO()
|
||||||
|
result = self.delete_vnf_instance.take_action(parsed_args)
|
||||||
|
self.assertIsNone(result)
|
||||||
|
self.assertEqual(("Vnf instance '%s' deleted successfully")
|
||||||
|
% self.vnf_instances[0]['id'],
|
||||||
|
buffer.getvalue().strip())
|
||||||
|
|
||||||
|
def test_delete_multiple_vnf_instance(self):
|
||||||
|
arglist = []
|
||||||
|
for vnf_pkg in self.vnf_instances:
|
||||||
|
arglist.append(vnf_pkg['id'])
|
||||||
|
verifylist = [('vnf_instances', arglist)]
|
||||||
|
parsed_args = self.check_parser(self.delete_vnf_instance, arglist,
|
||||||
|
verifylist)
|
||||||
|
for i in range(0, 3):
|
||||||
|
self._mock_request_url_for_delete(i)
|
||||||
|
sys.stdout = buffer = StringIO()
|
||||||
|
result = self.delete_vnf_instance.take_action(parsed_args)
|
||||||
|
self.assertIsNone(result)
|
||||||
|
self.assertEqual('All specified vnf instances are deleted '
|
||||||
|
'successfully', buffer.getvalue().strip())
|
||||||
|
|
||||||
|
def test_delete_multiple_vnf_instance_exception(self):
|
||||||
|
arglist = [
|
||||||
|
self.vnf_instances[0]['id'],
|
||||||
|
'xxxx-yyyy-zzzz',
|
||||||
|
self.vnf_instances[1]['id'],
|
||||||
|
]
|
||||||
|
verifylist = [('vnf_instances', arglist)]
|
||||||
|
parsed_args = self.check_parser(self.delete_vnf_instance,
|
||||||
|
arglist, verifylist)
|
||||||
|
|
||||||
|
self._mock_request_url_for_delete(0)
|
||||||
|
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
'xxxx-yyyy-zzzz')
|
||||||
|
self.requests_mock.register_uri(
|
||||||
|
'GET', url, exc=exceptions.ConnectionFailed)
|
||||||
|
|
||||||
|
self._mock_request_url_for_delete(1)
|
||||||
|
exception = self.assertRaises(exceptions.CommandError,
|
||||||
|
self.delete_vnf_instance.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
self.assertEqual('Failed to delete 1 of 3 vnf instances.',
|
||||||
|
exception.message)
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from oslo_utils.fixture import uuidsentinel
|
from oslo_utils.fixture import uuidsentinel
|
||||||
|
from oslo_utils import uuidutils
|
||||||
|
|
||||||
|
|
||||||
def vnf_instance_response(attrs=None, instantiation_state='NOT_INSTANTIATED'):
|
def vnf_instance_response(attrs=None, instantiation_state='NOT_INSTANTIATED'):
|
||||||
@@ -104,6 +105,9 @@ def vnf_instance_response(attrs=None, instantiation_state='NOT_INSTANTIATED'):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Overwrite default attributes.
|
||||||
|
dummy_vnf_instance.update(attrs)
|
||||||
|
|
||||||
return dummy_vnf_instance
|
return dummy_vnf_instance
|
||||||
|
|
||||||
|
|
||||||
@@ -115,3 +119,17 @@ def get_vnflcm_data(vnf_instance):
|
|||||||
"""
|
"""
|
||||||
# return the list of data as per column order
|
# return the list of data as per column order
|
||||||
return tuple([vnf_instance[key] for key in sorted(vnf_instance.keys())])
|
return tuple([vnf_instance[key] for key in sorted(vnf_instance.keys())])
|
||||||
|
|
||||||
|
|
||||||
|
def create_vnf_instances(count=2):
|
||||||
|
"""Create multiple fake vnf instances.
|
||||||
|
|
||||||
|
:param count: The number of vnf instances to fake
|
||||||
|
:return:
|
||||||
|
A list of fake vnf instances dictionary
|
||||||
|
"""
|
||||||
|
vnf_instances = []
|
||||||
|
for i in range(0, count):
|
||||||
|
unique_id = uuidutils.generate_uuid()
|
||||||
|
vnf_instances.append(vnf_instance_response(attrs={'id': unique_id}))
|
||||||
|
return vnf_instances
|
||||||
|
@@ -800,6 +800,15 @@ class VnfLCMClient(ClientBase):
|
|||||||
return self.post((self.vnf_instance_path + "/instantiate") % vnf_id,
|
return self.post((self.vnf_instance_path + "/instantiate") % vnf_id,
|
||||||
body=body)
|
body=body)
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def terminate_vnf_instance(self, vnf_id, body):
|
||||||
|
return self.post((self.vnf_instance_path + "/terminate") % vnf_id,
|
||||||
|
body=body)
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def delete_vnf_instance(self, vnf_id):
|
||||||
|
return self.delete(self.vnf_instance_path % vnf_id)
|
||||||
|
|
||||||
|
|
||||||
class Client(object):
|
class Client(object):
|
||||||
"""Unified interface to interact with multiple applications of tacker service.
|
"""Unified interface to interact with multiple applications of tacker service.
|
||||||
@@ -1058,3 +1067,9 @@ class Client(object):
|
|||||||
|
|
||||||
def instantiate_vnf_instance(self, vnf_id, body):
|
def instantiate_vnf_instance(self, vnf_id, body):
|
||||||
return self.vnf_lcm_client.instantiate_vnf_instance(vnf_id, body)
|
return self.vnf_lcm_client.instantiate_vnf_instance(vnf_id, body)
|
||||||
|
|
||||||
|
def terminate_vnf_instance(self, vnf_id, body):
|
||||||
|
return self.vnf_lcm_client.terminate_vnf_instance(vnf_id, body)
|
||||||
|
|
||||||
|
def delete_vnf_instance(self, vnf_id):
|
||||||
|
return self.vnf_lcm_client.delete_vnf_instance(vnf_id)
|
||||||
|
Reference in New Issue
Block a user