Support ChangeVNFPackage command in tackerclient
Add ``openstack vnflcm change_vnfpkg`` to python-tackerclient. This command can execute change current vnf package operation [1]. [1] https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/003/03.03.01_60/gs_NFV-SOL003v030301p.pdf Implements: blueprint upgrade-vnf-package Change-Id: I0d9c88147dee3a273cb27224db6be6c91cf7fe55
This commit is contained in:
parent
b7f27c3dc6
commit
ab901b6466
@ -110,6 +110,7 @@ openstack.tackerclient.v2 =
|
|||||||
vnflcm_list = tackerclient.osc.v1.vnflcm.vnflcm:ListVnfLcm
|
vnflcm_list = tackerclient.osc.v1.vnflcm.vnflcm:ListVnfLcm
|
||||||
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_terminate = tackerclient.osc.v1.vnflcm.vnflcm:TerminateVnfLcm
|
||||||
|
vnflcm_change-vnfpkg = tackerclient.osc.v1.vnflcm.vnflcm:ChangeVnfPkgVnfLcm
|
||||||
vnflcm_delete = tackerclient.osc.v1.vnflcm.vnflcm:DeleteVnfLcm
|
vnflcm_delete = tackerclient.osc.v1.vnflcm.vnflcm:DeleteVnfLcm
|
||||||
vnflcm_op_list = tackerclient.osc.v1.vnflcm.vnflcm_op_occs:ListVnfLcmOp
|
vnflcm_op_list = tackerclient.osc.v1.vnflcm.vnflcm_op_occs:ListVnfLcmOp
|
||||||
vnflcm_op_show = tackerclient.osc.v1.vnflcm.vnflcm_op_occs:ShowVnfLcmOp
|
vnflcm_op_show = tackerclient.osc.v1.vnflcm.vnflcm_op_occs:ShowVnfLcmOp
|
||||||
|
@ -207,6 +207,10 @@ class InvalidInput(TackerClientException):
|
|||||||
message = _("Invalid input: %(reason)s")
|
message = _("Invalid input: %(reason)s")
|
||||||
|
|
||||||
|
|
||||||
|
class UnsupportedCommandVersion(TackerClientException):
|
||||||
|
message = _("This command is not supported in version %(version)s")
|
||||||
|
|
||||||
|
|
||||||
# Command line exceptions
|
# Command line exceptions
|
||||||
|
|
||||||
class TackerCLIError(TackerException):
|
class TackerCLIError(TackerException):
|
||||||
|
@ -566,3 +566,30 @@ class ChangeExtConnVnfLcm(command.Command):
|
|||||||
if not result:
|
if not result:
|
||||||
print((_('Change External VNF Connectivity for VNF Instance %s '
|
print((_('Change External VNF Connectivity for VNF Instance %s '
|
||||||
'has been accepted.') % parsed_args.vnf_instance))
|
'has been accepted.') % parsed_args.vnf_instance))
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeVnfPkgVnfLcm(command.Command):
|
||||||
|
_description = _("Change Current VNF Package")
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ChangeVnfPkgVnfLcm, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
_VNF_INSTANCE,
|
||||||
|
metavar="<vnf-instance>",
|
||||||
|
help=_("VNF instance ID to Change Current VNF Package"))
|
||||||
|
parser.add_argument(
|
||||||
|
'request_file',
|
||||||
|
metavar="<param-file>",
|
||||||
|
help=_("Specify change-vnfpkg request parameters "
|
||||||
|
"in a json file."))
|
||||||
|
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
client = self.app.client_manager.tackerclient
|
||||||
|
result = client.change_vnfpkg_vnf_instance(
|
||||||
|
parsed_args.vnf_instance, jsonfile2body(
|
||||||
|
parsed_args.request_file))
|
||||||
|
if not result:
|
||||||
|
print((_('Change Current VNF Package for VNF Instance %s '
|
||||||
|
'has been accepted.') % parsed_args.vnf_instance))
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"vnfdId": "c6595341-a5bb-8246-53c4-7aeb843d60c5",
|
||||||
|
"additionalParams": {
|
||||||
|
"upgrade_type": "RollingUpdate",
|
||||||
|
"lcm-operation-coordinate-old-vnf": "./Scripts/coordinate_old_vnf.py",
|
||||||
|
"lcm-operation-coordinate-old-vnf-class": "CoordinateOldVnf",
|
||||||
|
"lcm-operation-coordinate-new-vnf": "./Scripts/coordinate_new_vnf.py",
|
||||||
|
"lcm-operation-coordinate-new-vnf-class": "CoordinateNewVnf",
|
||||||
|
"vdu_params": [{
|
||||||
|
"vduId": "VDU1",
|
||||||
|
"old_vnfc_param": {
|
||||||
|
"cp_name": "VDU1_CP1",
|
||||||
|
"username": "ubuntu",
|
||||||
|
"password": "ubuntu"
|
||||||
|
},
|
||||||
|
"new_vnfc_param": {
|
||||||
|
"cp_name": "VDU1_CP1",
|
||||||
|
"username": "ubuntu",
|
||||||
|
"password": "ubuntu"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"vduId": "VDU2",
|
||||||
|
"old_vnfc_param": {
|
||||||
|
"cp_name": "VDU2_CP1",
|
||||||
|
"username": "ubuntu",
|
||||||
|
"password": "ubuntu"
|
||||||
|
},
|
||||||
|
"new_vnfc_param": {
|
||||||
|
"cp_name": "VDU2_CP1",
|
||||||
|
"username": "ubuntu",
|
||||||
|
"password": "ubuntu"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -850,6 +850,40 @@ class TestChangeExtConnVnfLcm(TestVnfLcm):
|
|||||||
self.assertIn(expected_msg, str(ex))
|
self.assertIn(expected_msg, str(ex))
|
||||||
|
|
||||||
|
|
||||||
|
class TestChangeVnfPkgVnfLcm(TestVnfLcm):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestChangeVnfPkgVnfLcm, self).setUp()
|
||||||
|
self.change_vnfpkg_vnf_lcm = vnflcm.ChangeVnfPkgVnfLcm(
|
||||||
|
self.app, self.app_args,
|
||||||
|
cmd_name='vnflcm change-vnfpkg')
|
||||||
|
|
||||||
|
def test_take_action_with_v1_version(self):
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
sample_param_file = ("./tackerclient/osc/v2/vnflcm/samples/"
|
||||||
|
"change_vnfpkg_vnf_instance_param_sample.json")
|
||||||
|
arglist = [vnf_instance['id'], sample_param_file]
|
||||||
|
verifylist = [('vnf_instance', vnf_instance['id']),
|
||||||
|
('request_file', sample_param_file)]
|
||||||
|
|
||||||
|
# command param
|
||||||
|
parsed_args = self.check_parser(self.change_vnfpkg_vnf_lcm,
|
||||||
|
arglist,
|
||||||
|
verifylist)
|
||||||
|
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v1/vnf_instances',
|
||||||
|
vnf_instance['id'], 'change_vnfpkg')
|
||||||
|
self.requests_mock.register_uri(
|
||||||
|
'POST', url, headers=self.header, status_code=400, json={})
|
||||||
|
|
||||||
|
ex = self.assertRaises(exceptions.UnsupportedCommandVersion,
|
||||||
|
self.change_vnfpkg_vnf_lcm.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
expected_msg = "This command is not supported in version 1"
|
||||||
|
self.assertEqual(expected_msg, str(ex))
|
||||||
|
|
||||||
|
|
||||||
class TestVnfLcmV1(base.FixturedTestCase):
|
class TestVnfLcmV1(base.FixturedTestCase):
|
||||||
client_fixture_class = client.ClientFixture
|
client_fixture_class = client.ClientFixture
|
||||||
api_version = '1'
|
api_version = '1'
|
||||||
|
@ -13,8 +13,18 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from io import StringIO
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from tackerclient.common import exceptions
|
||||||
|
from tackerclient.osc.v1.vnflcm import vnflcm
|
||||||
from tackerclient.tests.unit.osc import base
|
from tackerclient.tests.unit.osc import base
|
||||||
from tackerclient.tests.unit.osc.v1.fixture_data import client
|
from tackerclient.tests.unit.osc.v1.fixture_data import client
|
||||||
|
from tackerclient.tests.unit.osc.v1 import test_vnflcm
|
||||||
|
from tackerclient.tests.unit.osc.v1 import vnflcm_fakes
|
||||||
|
from tackerclient.v1_0 import client as proxy_client
|
||||||
|
|
||||||
|
|
||||||
class TestVnfLcmV2(base.FixturedTestCase):
|
class TestVnfLcmV2(base.FixturedTestCase):
|
||||||
@ -30,3 +40,112 @@ class TestVnfLcmV2(base.FixturedTestCase):
|
|||||||
self.assertEqual(self.cs.vnf_lcm_client.vnf_instances_path,
|
self.assertEqual(self.cs.vnf_lcm_client.vnf_instances_path,
|
||||||
'/vnflcm/v2/vnf_instances')
|
'/vnflcm/v2/vnf_instances')
|
||||||
# check of other paths is omitted.
|
# check of other paths is omitted.
|
||||||
|
|
||||||
|
|
||||||
|
class TestChangeVnfPkgVnfLcm(test_vnflcm.TestVnfLcm):
|
||||||
|
api_version = '2'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestChangeVnfPkgVnfLcm, self).setUp()
|
||||||
|
self.change_vnfpkg_vnf_lcm = vnflcm.ChangeVnfPkgVnfLcm(
|
||||||
|
self.app, self.app_args,
|
||||||
|
cmd_name='vnflcm change-vnfpkg')
|
||||||
|
|
||||||
|
def test_take_action(self):
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
sample_param_file = ("./tackerclient/osc/v2/vnflcm/samples/"
|
||||||
|
"change_vnfpkg_vnf_instance_param_sample.json")
|
||||||
|
|
||||||
|
arglist = [vnf_instance['id'], sample_param_file]
|
||||||
|
verifylist = [('vnf_instance', vnf_instance['id']),
|
||||||
|
('request_file', sample_param_file)]
|
||||||
|
|
||||||
|
# command param
|
||||||
|
parsed_args = self.check_parser(self.change_vnfpkg_vnf_lcm,
|
||||||
|
arglist,
|
||||||
|
verifylist)
|
||||||
|
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v2/vnf_instances',
|
||||||
|
vnf_instance['id'], 'change_vnfpkg')
|
||||||
|
self.requests_mock.register_uri(
|
||||||
|
'POST', url, headers=self.header, json={})
|
||||||
|
|
||||||
|
sys.stdout = buffer = StringIO()
|
||||||
|
with mock.patch.object(proxy_client.ClientBase,
|
||||||
|
'_handle_fault_response') as m:
|
||||||
|
self.change_vnfpkg_vnf_lcm.take_action(parsed_args)
|
||||||
|
# check no fault response is received
|
||||||
|
self.assertNotCalled(m)
|
||||||
|
self.assertEqual(
|
||||||
|
('Change Current VNF Package for VNF Instance {0} '
|
||||||
|
'has been accepted.'.format(vnf_instance['id'])),
|
||||||
|
buffer.getvalue().strip())
|
||||||
|
|
||||||
|
def test_take_action_vnf_instance_not_found(self):
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
sample_param_file = ("./tackerclient/osc/v1/vnflcm/samples/"
|
||||||
|
"change_vnfpkg_vnf_instance_param_sample.json")
|
||||||
|
arglist = [vnf_instance['id'], sample_param_file]
|
||||||
|
verifylist = [('vnf_instance', vnf_instance['id']),
|
||||||
|
('request_file', sample_param_file)]
|
||||||
|
|
||||||
|
# command param
|
||||||
|
parsed_args = self.check_parser(self.change_vnfpkg_vnf_lcm,
|
||||||
|
arglist,
|
||||||
|
verifylist)
|
||||||
|
|
||||||
|
url = os.path.join(self.url, 'vnflcm/v2/vnf_instances',
|
||||||
|
vnf_instance['id'], 'change_vnfpkg')
|
||||||
|
self.requests_mock.register_uri(
|
||||||
|
'POST', url, headers=self.header, status_code=404, json={})
|
||||||
|
|
||||||
|
self.assertRaises(exceptions.TackerClientException,
|
||||||
|
self.change_vnfpkg_vnf_lcm.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
def test_take_action_param_file_not_exists(self):
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
sample_param_file = "./not_exists.json"
|
||||||
|
arglist = [vnf_instance['id'], sample_param_file]
|
||||||
|
verifylist = [('vnf_instance', vnf_instance['id']),
|
||||||
|
('request_file', sample_param_file)]
|
||||||
|
|
||||||
|
# command param
|
||||||
|
parsed_args = self.check_parser(
|
||||||
|
self.change_vnfpkg_vnf_lcm,
|
||||||
|
arglist,
|
||||||
|
verifylist)
|
||||||
|
|
||||||
|
ex = self.assertRaises(
|
||||||
|
exceptions.InvalidInput,
|
||||||
|
self.change_vnfpkg_vnf_lcm.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
expected_msg = ("Invalid input: File %s does not exist "
|
||||||
|
"or user does not have read privileges to it")
|
||||||
|
self.assertEqual(expected_msg % sample_param_file, str(ex))
|
||||||
|
|
||||||
|
@mock.patch("os.open")
|
||||||
|
@mock.patch("os.access")
|
||||||
|
def test_take_action_invalid_format_param_file(self, mock_access,
|
||||||
|
mock_open):
|
||||||
|
vnf_instance = vnflcm_fakes.vnf_instance_response()
|
||||||
|
sample_param_file = "./invalid_param_file.json"
|
||||||
|
arglist = [vnf_instance['id'], sample_param_file]
|
||||||
|
verifylist = [('vnf_instance', vnf_instance['id']),
|
||||||
|
('request_file', sample_param_file)]
|
||||||
|
|
||||||
|
mock_open.return_value = "invalid_json_data"
|
||||||
|
mock_access.return_value = True
|
||||||
|
# command param
|
||||||
|
parsed_args = self.check_parser(self.change_vnfpkg_vnf_lcm,
|
||||||
|
arglist,
|
||||||
|
verifylist)
|
||||||
|
|
||||||
|
ex = self.assertRaises(
|
||||||
|
exceptions.InvalidInput,
|
||||||
|
self.change_vnfpkg_vnf_lcm.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
expected_msg = "Failed to load parameter file."
|
||||||
|
self.assertIn(expected_msg, str(ex))
|
||||||
|
@ -966,6 +966,15 @@ class VnfLCMClient(ClientBase):
|
|||||||
return self.post((self.vnf_instance_path + "/change_ext_conn") %
|
return self.post((self.vnf_instance_path + "/change_ext_conn") %
|
||||||
vnf_id, body=body, headers=self.headers)
|
vnf_id, body=body, headers=self.headers)
|
||||||
|
|
||||||
|
@APIParamsCall
|
||||||
|
def change_vnfpkg_vnf_instance(self, vnf_id, body):
|
||||||
|
# NOTE: it is only supported by V2-API.
|
||||||
|
if self.vnf_instance_path.split('/')[2] == 'v2':
|
||||||
|
return self.post((self.vnf_instance_path + "/change_vnfpkg") %
|
||||||
|
vnf_id, body=body, headers=self.headers)
|
||||||
|
else:
|
||||||
|
raise exceptions.UnsupportedCommandVersion(version='1')
|
||||||
|
|
||||||
@APIParamsCall
|
@APIParamsCall
|
||||||
def retry_vnf_instance(self, occ_id):
|
def retry_vnf_instance(self, occ_id):
|
||||||
return self.post((self.vnf_lcm_op_occs_path + "/retry") % occ_id,
|
return self.post((self.vnf_lcm_op_occs_path + "/retry") % occ_id,
|
||||||
@ -1272,6 +1281,9 @@ class Client(object):
|
|||||||
def change_ext_conn_vnf_instance(self, vnf_id, body):
|
def change_ext_conn_vnf_instance(self, vnf_id, body):
|
||||||
return self.vnf_lcm_client.change_ext_conn_vnf_instance(vnf_id, body)
|
return self.vnf_lcm_client.change_ext_conn_vnf_instance(vnf_id, body)
|
||||||
|
|
||||||
|
def change_vnfpkg_vnf_instance(self, vnf_id, body):
|
||||||
|
return self.vnf_lcm_client.change_vnfpkg_vnf_instance(vnf_id, body)
|
||||||
|
|
||||||
def delete_vnf_instance(self, vnf_id):
|
def delete_vnf_instance(self, vnf_id):
|
||||||
return self.vnf_lcm_client.delete_vnf_instance(vnf_id)
|
return self.vnf_lcm_client.delete_vnf_instance(vnf_id)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user