OSC support to create vnf using vnflcm API

Added a new command ``openstack vnflcm create`` to create a new vnf.

Blueprint: support-etsi-nfv-specs
Change-Id: Ia90955df6ac141661c3d58e4de4e098c4cb51aab
This commit is contained in:
Shubham Potale 2019-12-10 15:39:20 +05:30 committed by Shubham
parent e712c255d0
commit 66efce28d4
8 changed files with 245 additions and 3 deletions

View File

@ -34,7 +34,7 @@ oslo.context==2.19.2
oslo.i18n==3.15.3
oslo.log==3.36.0
oslo.serialization==2.18.0
oslo.utils==3.33.0
oslo.utils==3.40.0
pbr==2.0.0
pep8==1.5.7
positional==1.2.1

View File

@ -14,5 +14,5 @@ Babel!=2.4.0,>=2.3.4 # BSD
oslo.i18n>=3.15.3 # Apache-2.0
osc-lib>=1.8.0 # Apache-2.0
oslo.log>=3.36.0 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0
oslo.utils>=3.40.0 # Apache-2.0
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0

View File

@ -83,7 +83,7 @@ openstack.tackerclient.v1 =
vnf_package_show = tackerclient.osc.v1.vnfpkgm.vnf_package:ShowVnfPackage
vnf_package_upload = tackerclient.osc.v1.vnfpkgm.vnf_package:UploadVnfPackage
vnf_package_delete = tackerclient.osc.v1.vnfpkgm.vnf_package:DeleteVnfPackage
vnflcm_create = tackerclient.osc.v1.vnflcm.vnflcm:CreateVnfLcm
[build_releasenotes]
all_files = 1

View File

View File

@ -0,0 +1,82 @@
# 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.
from osc_lib.command import command
from osc_lib import utils
from tackerclient.i18n import _
from tackerclient.osc import sdk_utils
_mixed_case_fields = ('vnfInstanceName', 'vnfInstanceDescription', 'vnfdId',
'vnfProvider', 'vnfProductName', 'vnfSoftwareVersion',
'vnfdVersion', 'instantiationState')
def _get_columns(item):
column_map = {
'id': 'ID',
'vnfInstanceName': 'VNF Instance Name',
'vnfInstanceDescription': 'VNF Instance Description',
'vnfdId': 'VNFD ID',
'vnfProvider': 'VNF Provider',
'vnfProductName': 'VNF Product Name',
'vnfSoftwareVersion': 'VNF Software Version',
'vnfdVersion': 'VNFD Version',
'instantiationState': 'Instantiation State',
'links': 'Links',
}
return sdk_utils.get_osc_show_columns_for_sdk_resource(item, column_map)
class CreateVnfLcm(command.ShowOne):
_description = _("Create a new VNF Instance")
def get_parser(self, prog_name):
parser = super(CreateVnfLcm, self).get_parser(prog_name)
parser.add_argument(
'vnfd_id',
metavar="<vnfd-id>",
help=_('Identifier that identifies the VNFD which defines the '
'VNF instance to be created.'))
parser.add_argument(
'--name',
metavar="<vnf-instance-name>",
help=_('Name of the VNF instance to be created.'))
parser.add_argument(
'--description',
metavar="<vnf-instance-description>",
help=_('Description of the VNF instance to be created.'))
return parser
def args2body(self, parsed_args):
body = {}
body['vnfdId'] = parsed_args.vnfd_id
if parsed_args.description:
body['vnfInstanceDescription'] = parsed_args.description
if parsed_args.name:
body['vnfInstanceName'] = parsed_args.name
return body
def take_action(self, parsed_args):
client = self.app.client_manager.tackerclient
vnf = client.create_vnf_instance(self.args2body(parsed_args))
display_columns, columns = _get_columns(vnf)
data = utils.get_item_properties(
sdk_utils.DictModel(vnf),
columns, mixed_case_fields=_mixed_case_fields)
return (display_columns, data)

View File

@ -0,0 +1,84 @@
# 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 ddt
import mock
import os
from oslo_utils.fixture import uuidsentinel
from tackerclient.osc.v1.vnflcm import vnflcm
from tackerclient.tests.unit.osc import base
from tackerclient.tests.unit.osc.v1.fixture_data import client
from tackerclient.tests.unit.osc.v1 import vnflcm_fakes
class TestVnfLcm(base.FixturedTestCase):
client_fixture_class = client.ClientFixture
def setUp(self):
super(TestVnfLcm, self).setUp()
self.url = client.TACKER_URL
self.header = {'content-type': 'application/json'}
self.app = mock.Mock()
self.app_args = mock.Mock()
self.client_manager = self.cs
self.app.client_manager.tackerclient = self.client_manager
def _get_columns_vnflcm():
columns = ['ID', 'Instantiation State', 'VNF Instance Description',
'VNF Instance Name', 'VNF Product Name', 'VNF Provider',
'VNF Software Version', 'VNFD ID', 'VNFD Version', 'Links']
return columns
@ddt.ddt
class TestCreateVnfLcm(TestVnfLcm):
def setUp(self):
super(TestCreateVnfLcm, self).setUp()
self.create_vnf_lcm = vnflcm.CreateVnfLcm(
self.app, self.app_args, cmd_name='vnflcm create')
def test_create_no_args(self):
self.assertRaises(base.ParserException, self.check_parser,
self.create_vnf_lcm, [], [])
@ddt.data(True, False)
def test_take_action(self, optional_arguments):
arglist = [uuidsentinel.vnf_package_vnfd_id]
verifylist = [('vnfd_id', uuidsentinel.vnf_package_vnfd_id)]
if optional_arguments:
arglist.extend(['--name', 'test',
'--description', 'test'])
verifylist.extend([('name', 'test'),
('description', 'test')])
# command param
parsed_args = self.check_parser(self.create_vnf_lcm, arglist,
verifylist)
json = vnflcm_fakes.vnf_instance_response()
self.requests_mock.register_uri(
'POST', os.path.join(self.url, 'vnflcm/v1/vnf_instances'),
json=json, headers=self.header)
columns, data = (self.create_vnf_lcm.take_action(parsed_args))
self.assertItemsEqual(_get_columns_vnflcm(),
columns)
self.assertItemsEqual(vnflcm_fakes.get_vnflcm_data(json),
data)

View File

@ -0,0 +1,53 @@
# 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.
from oslo_utils.fixture import uuidsentinel
def vnf_instance_response(attrs=None):
"""Create a fake vnf instance.
:param Dictionary attrs:
A dictionary with all attributes
:return:
A vnf instance dict
"""
attrs = attrs or {}
# Set default attributes.
dummy_vnf_instance = {
"id": uuidsentinel.vnf_instance_id,
"vnfInstanceName": "Fake-VNF-Instance",
"vnfInstanceDescription": "Fake VNF",
"vnfdId": uuidsentinel.vnf_package_vnfd_id,
"vnfProvider": "NTT NS lab",
"vnfProductName": "Sample VNF",
"vnfSoftwareVersion": "1.0",
"vnfdVersion": "1.0",
"instantiationState": "NOT_INSTANTIATED",
"links": "vnflcm/v1/vnf_instances/" + uuidsentinel.vnf_instance_id +
"/instantiate"
}
return dummy_vnf_instance
def get_vnflcm_data(vnf_instance):
"""Get the vnf instance data.
:return:
A tuple object sorted based on the name of the columns.
"""
# return the list of data as per column order
return tuple([vnf_instance[key] for key in sorted(vnf_instance.keys())])

View File

@ -774,6 +774,23 @@ class VnfPackageClient(ClientBase):
body=file_data)
class VnfLCMClient(ClientBase):
"""Client for vnflcm APIs.
Purpose of this class is to create required request url for vnflcm
APIs.
"""
vnf_instances_path = '/vnflcm/v1/vnf_instances'
def build_action(self, action):
return action
@APIParamsCall
def create_vnf_instance(self, body):
return self.post(self.vnf_instances_path, body=body)
class Client(object):
"""Unified interface to interact with multiple applications of tacker service.
@ -794,6 +811,7 @@ class Client(object):
"""
def __init__(self, **kwargs):
self.vnf_lcm_client = VnfLCMClient(**kwargs)
self.vnf_package_client = VnfPackageClient(**kwargs)
self.legacy_client = LegacyClient(**kwargs)
@ -1018,3 +1036,8 @@ class Client(object):
def delete_vnf_package(self, vnf_package):
return self.vnf_package_client.delete_vnf_package(vnf_package)
# VnfLCMClient methods.
def create_vnf_instance(self, body):
return self.vnf_lcm_client.create_vnf_instance(body)