Add command for upload vnf package API

Added support vnf package upload command and their unit test cases.

Please see result here.
http://paste.openstack.org/show/766299/

Change-Id: I88da4e209413a00d52c73fc83983ed2f5fd273c6
Implements: bp tosca-csar-mgmt-driver
This commit is contained in:
Shubham Potale 2019-08-26 21:16:26 +05:30 committed by dharmendra kushwaha
parent 11e23eed22
commit ffaf88505a
11 changed files with 2246 additions and 4 deletions

View File

@ -83,6 +83,7 @@ openstack.tackerclient.v1 =
vnf_package_create = tackerclient.osc.v1.vnfpkgm.vnf_package:CreateVnfPackage
vnf_package_list = tackerclient.osc.v1.vnfpkgm.vnf_package:ListVnfPackage
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

View File

@ -141,6 +141,66 @@ class ShowVnfPackage(command.ShowOne):
return (display_columns, data)
class UploadVnfPackage(command.Command):
_description = _("Upload VNF Package")
def get_parser(self, prog_name):
LOG.debug('get_parser(%s)', prog_name)
parser = super(UploadVnfPackage, self).get_parser(prog_name)
parser.add_argument(
'vnf_package',
metavar="<vnf-package>",
help=_("VNF package ID")
)
file_source = parser.add_mutually_exclusive_group(required=True)
file_source.add_argument(
"--path",
metavar="<file>",
help=_("Upload VNF CSAR package from local file"),
)
file_source.add_argument(
"--url",
metavar="<Uri>",
help=_("Uri of the VNF package content"),
)
parser.add_argument(
"--user-name",
metavar="<user-name>",
help=_("User name for authentication"),
)
parser.add_argument(
"--password",
metavar="<password>",
help=_("Password for authentication"),
)
return parser
def take_action(self, parsed_args):
client = self.app.client_manager.tackerclient
attrs = {}
if parsed_args.user_name:
attrs['userName'] = parsed_args.user_name
if parsed_args.password:
attrs['password'] = parsed_args.password
if parsed_args.url:
attrs['url'] = parsed_args.url
file_data = None
try:
if parsed_args.path:
file_data = open(parsed_args.path, 'rb')
result = client.upload_vnf_package(parsed_args.vnf_package,
file_data, **attrs)
if not result:
print((_('Upload request for VNF package %(id)s has been'
' accepted.') % {'id': parsed_args.vnf_package}))
finally:
if file_data:
file_data.close()
class DeleteVnfPackage(command.Command):
"""Vnf package delete

View File

@ -43,6 +43,14 @@ class FixturedTestCase(testtools.TestCase):
self.assertEqual(getattr(parsed_args, attr), value)
return parsed_args
def assertNotCalled(self, m, msg=None):
"""Assert a function was not called"""
if m.called:
if not msg:
msg = 'method %s should not have been called' % m
self.fail(msg)
class ParserException(Exception):
pass

View File

@ -0,0 +1,204 @@
# TODO:Manually change from version 1.2 to 1.0
tosca_definitions_version: tosca_simple_yaml_1_0
#tosca_definitions_version: tosca_simple_yaml_1_2
description: ETSI NFV SOL 001 common types definitions version 2.6.1
metadata:
template_name: etsi_nfv_sol001_common_types
template_author: ETSI_NFV
template_version: 2.6.1
data_types:
tosca.datatypes.nfv.L2AddressData:
derived_from: tosca.datatypes.Root
description: Describes the information on the MAC addresses to be assigned to a connection point.
properties:
mac_address_assignment:
type: boolean
description: Specifies if the address assignment is the responsibility of management and orchestration function or not. If it is set to True, it is the management and orchestration function responsibility
required: true
tosca.datatypes.nfv.L3AddressData:
derived_from: tosca.datatypes.Root
description: Provides information about Layer 3 level addressing scheme and parameters applicable to a CP
properties:
ip_address_assignment:
type: boolean
description: Specifies if the address assignment is the responsibility of management and orchestration function or not. If it is set to True, it is the management and orchestration function responsibility
required: true
floating_ip_activated:
type: boolean
description: Specifies if the floating IP scheme is activated on the Connection Point or not
required: true
ip_address_type:
type: string
description: Defines address type. The address type should be aligned with the address type supported by the layer_protocols properties of the parent VnfExtCp
required: false
constraints:
- valid_values: [ ipv4, ipv6 ]
number_of_ip_address:
type: integer
description: Minimum number of IP addresses to be assigned
required: false
constraints:
- greater_than: 0
tosca.datatypes.nfv.AddressData:
derived_from: tosca.datatypes.Root
description: Describes information about the addressing scheme and parameters applicable to a CP
properties:
address_type:
type: string
description: Describes the type of the address to be assigned to a connection point. The content type shall be aligned with the address type supported by the layerProtocol property of the connection point
required: true
constraints:
- valid_values: [ mac_address, ip_address ]
l2_address_data:
type: tosca.datatypes.nfv.L2AddressData
description: Provides the information on the MAC addresses to be assigned to a connection point.
required: false
l3_address_data:
type: tosca.datatypes.nfv.L3AddressData
description: Provides the information on the IP addresses to be assigned to a connection point
required: false
tosca.datatypes.nfv.ConnectivityType:
derived_from: tosca.datatypes.Root
description: describes additional connectivity information of a virtualLink
properties:
layer_protocols:
type: list
description: Identifies the protocol a virtualLink gives access to (ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire).The top layer protocol of the virtualLink protocol stack shall always be provided. The lower layer protocols may be included when there are specific requirements on these layers.
required: true
entry_schema:
type: string
constraints:
- valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
flow_pattern:
type: string
description: Identifies the flow pattern of the connectivity
required: false
constraints:
- valid_values: [ line, tree, mesh ]
tosca.datatypes.nfv.LinkBitrateRequirements:
derived_from: tosca.datatypes.Root
description: describes the requirements in terms of bitrate for a virtual link
properties:
root:
type: integer # in bits per second
description: Specifies the throughput requirement in bits per second of the link (e.g. bitrate of E-Line, root bitrate of E-Tree, aggregate capacity of E-LAN).
required: true
constraints:
- greater_or_equal: 0
leaf:
type: integer # in bits per second
description: Specifies the throughput requirement in bits per second of leaf connections to the link when applicable to the connectivity type (e.g. for E-Tree and E LAN branches).
required: false
constraints:
- greater_or_equal: 0
tosca.datatypes.nfv.CpProtocolData:
derived_from: tosca.datatypes.Root
description: Describes and associates the protocol layer that a CP uses together with other protocol and connection point information
properties:
associated_layer_protocol:
type: string
required: true
description: One of the values of the property layer_protocols of the CP
constraints:
- valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
address_data:
type: list
description: Provides information on the addresses to be assigned to the CP
entry_schema:
type: tosca.datatypes.nfv.AddressData
required: false
tosca.datatypes.nfv.VnfProfile:
derived_from: tosca.datatypes.Root
description: describes a profile for instantiating VNFs of a particular NS DF according to a specific VNFD and VNF DF.
properties:
instantiation_level:
type: string
description: Identifier of the instantiation level of the VNF DF to be used for instantiation. If not present, the default instantiation level as declared in the VNFD shall be used.
required: false
min_number_of_instances:
type: integer
description: Minimum number of instances of the VNF based on this VNFD that is permitted to exist for this VnfProfile.
required: true
constraints:
- greater_or_equal: 0
max_number_of_instances:
type: integer
description: Maximum number of instances of the VNF based on this VNFD that is permitted to exist for this VnfProfile.
required: true
constraints:
- greater_or_equal: 0
tosca.datatypes.nfv.Qos:
derived_from: tosca.datatypes.Root
description: describes QoS data for a given VL used in a VNF deployment flavour
properties:
latency:
type: scalar-unit.time #Number
description: Specifies the maximum latency
required: true
constraints:
- greater_than: 0 s
packet_delay_variation:
type: scalar-unit.time #Number
description: Specifies the maximum jitter
required: true
constraints:
- greater_or_equal: 0 s
packet_loss_ratio:
type: float
description: Specifies the maximum packet loss ratio
required: false
constraints:
- in_range: [ 0.0, 1.0 ]
capability_types:
tosca.capabilities.nfv.VirtualLinkable:
derived_from: tosca.capabilities.Node
description: A node type that includes the VirtualLinkable capability indicates that it can be pointed by tosca.relationships.nfv.VirtualLinksTo relationship type
relationship_types:
tosca.relationships.nfv.VirtualLinksTo:
derived_from: tosca.relationships.DependsOn
description: Represents an association relationship between the VduCp and VnfVirtualLink node types
valid_target_types: [ tosca.capabilities.nfv.VirtualLinkable ]
node_types:
tosca.nodes.nfv.Cp:
derived_from: tosca.nodes.Root
description: Provides information regarding the purpose of the connection point
properties:
layer_protocols:
type: list
description: Identifies which protocol the connection point uses for connectivity purposes
required: true
entry_schema:
type: string
constraints:
- valid_values: [ ethernet, mpls, odu2, ipv4, ipv6, pseudo-wire ]
role: #Name in ETSI NFV IFA011 v0.7.3: cpRole
type: string
description: Identifies the role of the port in the context of the traffic flow patterns in the VNF or parent NS
required: false
constraints:
- valid_values: [ root, leaf ]
description:
type: string
description: Provides human-readable information on the purpose of the connection point
required: false
protocol:
type: list
description: Provides information on the addresses to be assigned to the connection point(s) instantiated from this Connection Point Descriptor
required: false
entry_schema:
type: tosca.datatypes.nfv.CpProtocolData
trunk_mode:
type: boolean
description: Provides information about whether the CP instantiated from this Cp is in Trunk mode (802.1Q or other), When operating in "trunk mode", the Cp is capable of carrying traffic for several VLANs. Absence of this property implies that trunkMode is not configured for the Cp i.e. It is equivalent to boolean value "false".
required: false

View File

@ -0,0 +1,277 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: Simple deployment flavour for Sample VNF
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- helloworld3_types.yaml
topology_template:
inputs:
descriptor_id:
type: string
descriptor_version:
type: string
provider:
type: string
product_name:
type: string
software_version:
type: string
vnfm_info:
type: list
entry_schema:
type: string
flavour_id:
type: string
flavour_description:
type: string
substitution_mappings:
node_type: ntt.nslab.VNF
properties:
flavour_id: simple
requirements:
virtual_link_external: [ CP1, virtual_link ]
node_templates:
VNF:
type: ntt.nslab.VNF
properties:
flavour_description: A simple flavour
interfaces:
Vnflcm:
# supporting only 'instantiate', 'terminate', 'modify'
# not supporting LCM script, supporting only default LCM
instantiate: []
instantiate_start: []
instantiate_end: []
terminate: []
terminate_start: []
terminate_end: []
modify_information: []
modify_information_start: []
modify_information_end: []
# change_flavour: []
# change_flavour_start: []
# change_flavour_end: []
# change_external_connectivity: []
# change_external_connectivity_start: []
# change_external_connectivity_end: []
# operate: []
# operate_start: []
# operate_end: []
# heal: []
# heal_start: []
# heal_end: []
# scale: []
# scale_start: []
# scale_end: []
# scale_to_level: []
# scale_to_level_start: []
# scale_to_level_end: []
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU1
description: VDU1 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 1
sw_image_data:
name: Software of VDU1
version: '0.4.0'
checksum:
algorithm: sha-256
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
container_format: bare
disk_format: qcow2
min_disk: 1 GB
size: 1 GB
artifacts:
sw_image:
type: tosca.artifacts.nfv.SwImage
file: cirros-0.4.0-x86_64-disk.img
repository: http://download.cirros-cloud.net/0.4.0/
capabilities:
virtual_compute:
properties:
virtual_memory:
virtual_mem_size: 512 MB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GB
VDU2:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU2
description: VDU2 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
capabilities:
virtual_compute:
properties:
virtual_memory:
virtual_mem_size: 512 MB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GB
requirements:
- virtual_storage: VirtualStorage
VirtualStorage:
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
properties:
virtual_block_storage_data:
size_of_storage: 30 GB
rdma_enabled: true
sw_image_data:
name: VrtualStorage
version: '0.4.0'
checksum:
algorithm: sha-256
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
container_format: bare
disk_format: qcow2
min_disk: 2 GB
min_ram: 8192 MB
size: 2 GB
artifacts:
sw_image:
type: tosca.artifacts.nfv.SwImage
file: cirros-0.4.0-x86_64-disk.img
repository: http://download.cirros-cloud.net/0.4.0/
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
vnic_type: direct-physical
requirements:
- virtual_binding: VDU1
#- virtual_link: # the target node is determined in the NSD
CP2:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 1
requirements:
- virtual_binding: VDU1
- virtual_link: internalVL2
CP3:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 2
requirements:
- virtual_binding: VDU2
- virtual_link: internalVL2
internalVL2:
type: tosca.nodes.nfv.VnfVirtualLink
properties:
connectivity_type:
layer_protocols: [ ipv4 ]
description: Internal Virtual link in the VNF
vl_profile:
max_bitrate_requirements:
root: 1048576
leaf: 1048576
min_bitrate_requirements:
root: 1048576
leaf: 1048576
virtual_link_protocol_data:
- associated_layer_protocol: ipv4
l3_protocol_data:
ip_version: ipv4
cidr: 11.11.0.0/24
policies:
- scaling_aspects:
type: tosca.policies.nfv.ScalingAspects
properties:
aspects:
worker_instance:
name: worker_instance_aspect
description: worker_instance scaling aspect
max_scale_level: 2
step_deltas:
- delta_1
- VDU2_initial_delta:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 1
targets: [ VDU2 ]
- VDU2_scaling_aspect_deltas:
type: tosca.policies.nfv.VduScalingAspectDeltas
properties:
aspect: worker_instance
deltas:
delta_2:
number_of_instances: 1
targets: [ VDU2 ]
- instantiation_levels:
type: tosca.policies.nfv.InstantiationLevels
properties:
levels:
instantiation_level_1:
description: Smallest size
scale_info:
worker_instance:
scale_level: 0
instantiation_level_2:
description: Largest size
scale_info:
worker_instance:
scale_level: 2
default_level: instantiation_level_1
- VDU1_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 1
instantiation_level_2:
number_of_instances: 3
targets: [ VDU1 ]
- VDU2_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 1
instantiation_level_2:
number_of_instances: 1
targets: [ VDU2 ]
- internalVL2_instantiation_levels:
type: tosca.policies.nfv.VirtualLinkInstantiationLevels
properties:
levels:
instantiation_level_1:
bitrate_requirements:
root: 1048576
leaf: 1048576
instantiation_level_2:
bitrate_requirements:
root: 1048576
leaf: 1048576
targets: [ internalVL2 ]

View File

@ -0,0 +1,32 @@
tosca_definitions_version: tosca_simple_yaml_1_0
description: Sample VNF of NTT NS lab.
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
- helloworld3_types.yaml
- helloworld3_df_simple.yaml
# - helloworld3_df_complex.yaml
topology_template:
inputs:
selected_flavour:
type: string
description: VNF deployment flavour selected by the consumer. It is provided in the API
node_templates:
VNF:
type: ntt.nslab.VNF
properties:
flavour_id: { get_input: selected_flavour }
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
provider: NTT NS lab
product_name: Sample VNF
software_version: '1.0'
descriptor_version: '1.0'
vnfm_info:
- Tacker
requirements:
#- virtual_link_external # mapped in lower-level templates
#- virtual_link_internal # mapped in lower-level templates

View File

@ -0,0 +1,53 @@
tosca_definitions_version: tosca_simple_yaml_1_0
description: ntt.nslab.VNF type definition
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
node_types:
ntt.nslab.VNF:
derived_from: tosca.nodes.nfv.VNF
properties:
descriptor_id:
type: string
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 ] ]
default: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
descriptor_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
provider:
type: string
constraints: [ valid_values: [ 'NTT NS lab' ] ]
default: 'NTT NS lab'
product_name:
type: string
constraints: [ valid_values: [ 'Sample VNF' ] ]
default: 'Sample VNF'
software_version:
type: string
constraints: [ valid_values: [ '1.0' ] ]
default: '1.0'
vnfm_info:
type: list
entry_schema:
type: string
constraints: [ valid_values: [ Tacker ] ]
default: [ Tacker ]
flavour_id:
type: string
constraints: [ valid_values: [ simple ] ]
default: simple
flavour_description:
type: string
default: ""
requirements:
- virtual_link_external:
capability: tosca.capabilities.nfv.VirtualLinkable
- virtual_link_internal:
capability: tosca.capabilities.nfv.VirtualLinkable
interfaces:
Vnflcm:
type: tosca.interfaces.nfv.Vnflcm

View File

@ -0,0 +1,4 @@
TOSCA-Meta-File-Version: 1.0
Created-by: Hiroyuki JO
CSAR-Version: 1.1
Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml

View File

@ -13,6 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import shutil
import tempfile
import ddt
import mock
@ -22,6 +26,16 @@ from tackerclient.osc.v1.vnfpkgm import vnf_package
from tackerclient.tests.unit.osc import base
from tackerclient.tests.unit.osc.v1.fixture_data import client
from tackerclient.tests.unit.osc.v1 import vnf_package_fakes
from tackerclient.v1_0 import client as proxy_client
def _create_zip():
vnf_package_path = ('./tackerclient/tests//unit/osc/v1/fixture_data/'
'sample_vnf_package')
tmpdir = tempfile.mkdtemp()
tmparchive = os.path.join(tmpdir, 'sample_vnf_package')
zip_file = shutil.make_archive(tmparchive, 'zip', vnf_package_path)
return zip_file, tmpdir
def _get_columns_vnf_package(action='list', vnf_package_obj=None):
@ -213,3 +227,102 @@ class TestDeleteVnfPackage(TestVnfPackage):
self.assertRaises(exceptions.CommandError,
self.delete_vnf_package.take_action,
parsed_args)
@ddt.ddt
class TestUploadVnfPackage(TestVnfPackage):
# The new vnf package created.
_vnf_package = vnf_package_fakes.vnf_package_obj(
attrs={'userDefinedData': {'Test_key': 'Test_value'}})
def setUp(self):
super(TestUploadVnfPackage, self).setUp()
self.upload_vnf_package = vnf_package.UploadVnfPackage(
self.app, self.app_args, cmd_name='vnf package upload')
def test_upload_no_options(self):
self.assertRaises(base.ParserException, self.check_parser,
self.upload_vnf_package, [], [])
def _mock_request_url_for_upload(self, method, status_code=202, body={}):
if method == 'PUT':
self.header = {'content-type': 'application/zip'}
url = (self.url + '/vnfpkgm/v1/vnf_packages/' +
self._vnf_package['id'] + '/package_content')
else:
url = (self.url + '/vnfpkgm/v1/vnf_packages/' +
self._vnf_package['id'] + '/package_content/'
'upload_from_uri')
self.requests_mock.register_uri(method, url, json=body,
headers=self.header,
status_code=status_code)
def _get_arglist_and_verifylist(self, method, path):
if method == 'path':
arglist = [
self._vnf_package['id'],
"--path", path
]
verifylist = [
('path', path),
('vnf_package', self._vnf_package['id'])
]
else:
arglist = [
self._vnf_package['id'],
"--url", "http://uri:8000/test.zip",
"--user-name", "Test_username",
"--password", "Test_passoword",
]
verifylist = [
('url', "http://uri:8000/test.zip"),
('user_name', 'Test_username'),
('password', 'Test_passoword'),
('vnf_package', self._vnf_package['id'])
]
return arglist, verifylist
@ddt.data('path', 'url')
def test_upload_vnf_package(self, method):
path = None
if method == 'path':
zip_file, temp_dir = _create_zip()
path = zip_file
arglist, verifylist = self._get_arglist_and_verifylist(method,
path)
parsed_args = self.check_parser(self.upload_vnf_package, arglist,
verifylist)
with mock.patch.object(proxy_client.ClientBase,
'_handle_fault_response') as m:
if method == 'url':
self._mock_request_url_for_upload('POST')
self.upload_vnf_package.take_action(parsed_args)
else:
self._mock_request_url_for_upload('PUT')
self.upload_vnf_package.take_action(parsed_args)
# Delete temporary folder
shutil.rmtree(temp_dir)
# check no fault response is received
self.assertNotCalled(m)
def test_upload_vnf_package_with_conflict_error(self):
# Scenario in which vnf package is already in on-boarded state
zip_file, temp_dir = _create_zip()
arglist, verifylist = self._get_arglist_and_verifylist('path',
zip_file)
parsed_args = self.check_parser(self.upload_vnf_package, arglist,
verifylist)
body = {"conflictingRequest": {
"message": "VNF Package " + self._vnf_package['id'] +
" onboarding state is not CREATED", "code": 409}}
self._mock_request_url_for_upload('PUT', status_code=409, body=body)
self.assertRaises(exceptions.TackerClientException,
self.upload_vnf_package.take_action, parsed_args)
# Delete temporary folder
shutil.rmtree(temp_dir)

View File

@ -227,6 +227,8 @@ class ClientBase(object):
"""
if data is None:
return None
elif self.format == 'zip':
return data
elif type(data) is dict:
return serializer.Serializer(
self.get_attr_metadata()).serialize(data, self.content_type())
@ -236,7 +238,7 @@ class ClientBase(object):
def deserialize(self, data, status_code):
"""Deserializes an XML or JSON string into a dictionary."""
if status_code == 204:
if status_code in (204, 202):
return data
return serializer.Serializer(self.get_attr_metadata()).deserialize(
data, self.content_type())['body']
@ -737,9 +739,9 @@ class VnfPackageClient(ClientBase):
@APIParamsCall
def list_vnf_packages(self, retrieve_all=True, **_params):
vnf_package = self.list("vnf_packages", self.vnfpackages_path,
retrieve_all, **_params)
return vnf_package
vnf_packages = self.list("vnf_packages", self.vnfpackages_path,
retrieve_all, **_params)
return vnf_packages
@APIParamsCall
def show_vnf_package(self, vnf_package, **_params):
@ -749,6 +751,24 @@ class VnfPackageClient(ClientBase):
def delete_vnf_package(self, vnf_package):
return self.delete(self.vnfpackage_path % vnf_package)
@APIParamsCall
def upload_vnf_package(self, vnf_package, file_data=None, **attrs):
if attrs.get('url'):
json = {'addressInformation': attrs.get('url')}
for key in ['userName', 'password']:
if attrs.get(key):
json.update({key: attrs.get(key)})
return self.post(
'{base_path}/{id}/package_content/upload_from_uri'.format(
id=vnf_package, base_path=self.vnfpackages_path),
body=json)
else:
self.format = 'zip'
return self.put('{base_path}/{id}/package_content'.format(
id=vnf_package,
base_path=self.vnfpackages_path),
body=file_data)
class Client(object):
"""Unified interface to interact with multiple applications of tacker service.
@ -968,5 +988,9 @@ class Client(object):
def show_vnf_package(self, vnf_package, **_params):
return self.vnf_package_client.show_vnf_package(vnf_package, **_params)
def upload_vnf_package(self, vnf_package, file_data=None, **_params):
return self.vnf_package_client.upload_vnf_package(
vnf_package, file_data=file_data, **_params)
def delete_vnf_package(self, vnf_package):
return self.vnf_package_client.delete_vnf_package(vnf_package)