Implementation Artifacts support in Tacker
Implements: bp/add-artifacts-vnf-packages * python-tackerclient * Modify ``vnf package show`` command to display ``additionalArtifacts`` information. * Add new OSC command ``vnf package artifact`` to fetch individual artifact in an on-boarded VNF package. Change-Id: Id0694724f2f2e335c14824bc5ca5bf2e67ac4b96
This commit is contained in:
parent
60c268f04d
commit
9cd8f11d83
|
@ -84,6 +84,7 @@ openstack.tackerclient.v1 =
|
|||
vnf_package_delete = tackerclient.osc.v1.vnfpkgm.vnf_package:DeleteVnfPackage
|
||||
vnf_package_update = tackerclient.osc.v1.vnfpkgm.vnf_package:UpdateVnfPackage
|
||||
vnf_package_download = tackerclient.osc.v1.vnfpkgm.vnf_package:DownloadVnfPackage
|
||||
vnf_package_artifact_download = tackerclient.osc.v1.vnfpkgm.vnf_package:DownloadVnfPackageArtifact
|
||||
vnflcm_create = tackerclient.osc.v1.vnflcm.vnflcm:CreateVnfLcm
|
||||
vnflcm_show = tackerclient.osc.v1.vnflcm.vnflcm:ShowVnfLcm
|
||||
vnflcm_list = tackerclient.osc.v1.vnflcm.vnflcm:ListVnfLcm
|
||||
|
|
|
@ -32,13 +32,14 @@ LOG = logging.getLogger(__name__)
|
|||
formatters = {'softwareImages': tacker_osc_utils.FormatComplexDataColumn,
|
||||
'checksum': tacker_osc_utils.FormatComplexDataColumn,
|
||||
'_links': tacker_osc_utils.FormatComplexDataColumn,
|
||||
'userDefinedData': tacker_osc_utils.FormatComplexDataColumn}
|
||||
'userDefinedData': tacker_osc_utils.FormatComplexDataColumn,
|
||||
'additionalArtifacts': tacker_osc_utils.FormatComplexDataColumn}
|
||||
|
||||
|
||||
_mixed_case_fields = ('usageState', 'onboardingState', 'operationalState',
|
||||
'vnfProductName', 'softwareImages', 'userDefinedData',
|
||||
'vnfdId', 'vnfdVersion', 'vnfSoftwareVersion',
|
||||
'vnfProvider')
|
||||
'vnfProvider', 'additionalArtifacts')
|
||||
|
||||
|
||||
def _get_columns(vnf_package_obj):
|
||||
|
@ -59,7 +60,8 @@ def _get_columns(vnf_package_obj):
|
|||
'vnfProductName': 'VNF Product Name',
|
||||
'vnfdId': 'VNFD ID',
|
||||
'vnfdVersion': 'VNFD Version',
|
||||
'checksum': 'Checksum'
|
||||
'checksum': 'Checksum',
|
||||
'additionalArtifacts': 'Additional Artifacts'
|
||||
})
|
||||
|
||||
return sdk_utils.get_osc_show_columns_for_sdk_resource(vnf_package_obj,
|
||||
|
@ -146,7 +148,11 @@ class ListVnfPackage(command.Lister):
|
|||
exclude_fields=None, exclude_default=False):
|
||||
fields = ['id', 'vnfProductName', 'onboardingState',
|
||||
'usageState', 'operationalState', '_links']
|
||||
complex_fields = ['checksum', 'softwareImages', 'userDefinedData']
|
||||
complex_fields = [
|
||||
'checksum',
|
||||
'softwareImages',
|
||||
'userDefinedData',
|
||||
'additionalArtifacts']
|
||||
simple_fields = ['vnfdVersion', 'vnfProvider', 'vnfSoftwareVersion',
|
||||
'vnfdId']
|
||||
|
||||
|
@ -409,6 +415,51 @@ class DownloadVnfPackage(command.Command):
|
|||
sdk_utils.save_data(body, parsed_args.file)
|
||||
|
||||
|
||||
class DownloadVnfPackageArtifact(command.Command):
|
||||
_description = _("Download VNF package artifact of an on-boarded "
|
||||
"VNF package.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(DownloadVnfPackageArtifact, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"vnf_package",
|
||||
metavar="<vnf-package>",
|
||||
help=_("VNF package ID")
|
||||
)
|
||||
parser.add_argument(
|
||||
"artifact_path",
|
||||
metavar="<artifact-path>",
|
||||
help=_("The artifact file's path")
|
||||
)
|
||||
parser.add_argument(
|
||||
"--file",
|
||||
metavar="<FILE>",
|
||||
help=_("Local file to save downloaded VNF Package or VNFD data. "
|
||||
"If this is not specified and there is no redirection "
|
||||
"then data will not be saved.")
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.tackerclient
|
||||
if sys.stdout.isatty() and not (parsed_args.file):
|
||||
msg = (
|
||||
"No redirection or local file specified for downloaded "
|
||||
"vnf package artifact data. Please specify a "
|
||||
"local file with --file to "
|
||||
"save downloaded vnf package artifact data "
|
||||
"or use redirection.")
|
||||
sdk_utils.exit(msg)
|
||||
body = client.download_artifact_from_vnf_package(
|
||||
parsed_args.vnf_package, parsed_args.artifact_path)
|
||||
|
||||
if not parsed_args.file:
|
||||
print(body)
|
||||
return
|
||||
else:
|
||||
sdk_utils.save_data(body, parsed_args.file)
|
||||
|
||||
|
||||
class UpdateVnfPackage(command.ShowOne):
|
||||
_description = _("Update information about an individual VNF package")
|
||||
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
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
|
File diff suppressed because it is too large
Load Diff
|
@ -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 ]
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "Hello, World!"
|
|
@ -0,0 +1,8 @@
|
|||
TOSCA-Meta-File-Version: 1.0
|
||||
Created-by: Dummy User
|
||||
CSAR-Version: 1.1
|
||||
Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml
|
||||
|
||||
Source: Scripts/install.sh
|
||||
Algorithm: SHA-256
|
||||
Hash: 27bbdb25d8f4ed6d07d6f6581b86515e8b2f0059b236ef7b6f50d6674b34f02a
|
|
@ -56,9 +56,14 @@ def _get_columns_vnf_package(action='list', vnf_package_obj=None):
|
|||
if action in ['show', 'create']:
|
||||
if vnf_package_obj and vnf_package_obj[
|
||||
'onboardingState'] == 'ONBOARDED':
|
||||
columns.extend(['VNFD ID', 'VNF Provider', 'VNF Software Version',
|
||||
'VNFD Version', 'Software Images',
|
||||
'VNF Product Name', 'Checksum'])
|
||||
columns.extend(['VNFD ID',
|
||||
'VNF Provider',
|
||||
'VNF Software Version',
|
||||
'VNFD Version',
|
||||
'Software Images',
|
||||
'VNF Product Name',
|
||||
'Checksum',
|
||||
'Additional Artifacts'])
|
||||
|
||||
return columns
|
||||
|
||||
|
@ -127,7 +132,11 @@ class TestListVnfPackage(TestVnfPackage):
|
|||
|
||||
columns = ['Id', 'Vnf Product Name', 'Onboarding State', 'Usage State',
|
||||
'Operational State', 'Links']
|
||||
complex_columns = ['Checksum', 'Software Images', 'User Defined Data']
|
||||
complex_columns = [
|
||||
'Checksum',
|
||||
'Software Images',
|
||||
'User Defined Data',
|
||||
'Additional Artifacts']
|
||||
simple_columns = ['Vnfd Version', 'Vnf Provider', 'Vnfd Id',
|
||||
'Vnf Software Version']
|
||||
|
||||
|
@ -195,9 +204,11 @@ class TestListVnfPackage(TestVnfPackage):
|
|||
def test_take_action_with_exclude_fields(self):
|
||||
parsed_args = self.check_parser(
|
||||
self.list_vnf_package,
|
||||
["--exclude_fields", 'softwareImages,checksum,userDefinedData',
|
||||
["--exclude_fields", 'softwareImages,checksum,'
|
||||
'userDefinedData,additionalArtifacts',
|
||||
"--filter", '(eq,onboardingState,ONBOARDED)'],
|
||||
[('exclude_fields', 'softwareImages,checksum,userDefinedData'),
|
||||
[('exclude_fields', 'softwareImages,checksum,'
|
||||
'userDefinedData,additionalArtifacts'),
|
||||
('filter', '(eq,onboardingState,ONBOARDED)')])
|
||||
vnf_packages = self._get_vnf_packages(onboarded_vnf_package=True)
|
||||
updated_vnf_packages = {'vnf_packages': []}
|
||||
|
@ -205,10 +216,12 @@ class TestListVnfPackage(TestVnfPackage):
|
|||
vnf_pkg.pop('softwareImages')
|
||||
vnf_pkg.pop('checksum')
|
||||
vnf_pkg.pop('userDefinedData')
|
||||
vnf_pkg.pop('additionalArtifacts')
|
||||
updated_vnf_packages['vnf_packages'].append(vnf_pkg)
|
||||
self._get_mock_response_for_list_vnf_packages(
|
||||
'filter=(eq,onboardingState,ONBOARDED)&'
|
||||
'exclude_fields=softwareImages,checksum,userDefinedData',
|
||||
'exclude_fields=softwareImages,checksum,'
|
||||
'userDefinedData,additionalArtifacts',
|
||||
json=updated_vnf_packages)
|
||||
|
||||
actual_columns, data = self.list_vnf_package.take_action(parsed_args)
|
||||
|
@ -216,7 +229,7 @@ class TestListVnfPackage(TestVnfPackage):
|
|||
headers, columns = tacker_osc_utils.get_column_definitions(
|
||||
self.list_vnf_package.get_attributes(
|
||||
exclude_fields=['softwareImages', 'checksum',
|
||||
'userDefinedData']),
|
||||
'userDefinedData', 'additionalArtifacts']),
|
||||
long_listing=True)
|
||||
|
||||
for vnf_package_obj in updated_vnf_packages['vnf_packages']:
|
||||
|
@ -224,7 +237,7 @@ class TestListVnfPackage(TestVnfPackage):
|
|||
vnf_package_obj, columns=columns, list_action=True))
|
||||
expected_columns = self.get_list_columns(
|
||||
exclude_fields=['Software Images', 'Checksum',
|
||||
'User Defined Data'])
|
||||
'User Defined Data', 'Additional Artifacts'])
|
||||
self.assertCountEqual(expected_columns, actual_columns)
|
||||
self.assertListItemsEqual(expected_data, list(data))
|
||||
|
||||
|
@ -731,3 +744,60 @@ class TestDownloadVnfPackage(TestVnfPackage):
|
|||
"Downloaded contents don't match test file")
|
||||
self.assertTrue(self._check_valid_zip_file(local_file.name))
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestDownloadVnfPackageArtifact(TestVnfPackage):
|
||||
# The new vnf package created.
|
||||
_vnf_package = vnf_package_fakes.vnf_package_obj(
|
||||
attrs={'userDefinedData': {'Test_key': 'Test_value'}})
|
||||
|
||||
def setUp(self):
|
||||
super(TestDownloadVnfPackageArtifact, self).setUp()
|
||||
self.download_vnf_package_artifacts = vnf_package.\
|
||||
DownloadVnfPackageArtifact(
|
||||
self.app, self.app_args,
|
||||
cmd_name='vnf package artifact download')
|
||||
|
||||
def test_download_no_options(self):
|
||||
self.assertRaises(base.ParserException, self.check_parser,
|
||||
self.download_vnf_package_artifacts, [], [])
|
||||
|
||||
def _mock_request_url_for_download_artifacts(
|
||||
self, artifact_path, artifact_data):
|
||||
self.header = {'content-type': 'text/plain'}
|
||||
url = os.path.join(self.url, 'vnfpkgm/v1/vnf_packages',
|
||||
self._vnf_package['id'], 'artifacts', artifact_path)
|
||||
self.requests_mock.register_uri('GET', url,
|
||||
headers=self.header,
|
||||
text=artifact_data)
|
||||
|
||||
def _get_arglist_and_verifylist(self, localfile):
|
||||
arglist = [
|
||||
self._vnf_package['id'],
|
||||
localfile.name[1:],
|
||||
'--file', localfile.name
|
||||
]
|
||||
verifylist = [
|
||||
('vnf_package', self._vnf_package['id']),
|
||||
('artifact_path', localfile.name[1:]),
|
||||
('file', localfile.name)
|
||||
]
|
||||
return arglist, verifylist
|
||||
|
||||
def test_download_artifacts_from_vnf_package(self):
|
||||
test_file = ('./tackerclient/tests//unit/osc/v1/fixture_data/'
|
||||
'sample_vnf_package_artifacts/Scripts/'
|
||||
'install.sh')
|
||||
|
||||
local_file = tempfile.NamedTemporaryFile(suffix='install.sh')
|
||||
artifact_data = open(test_file, 'r').read()
|
||||
arglist, verifylist = self._get_arglist_and_verifylist(
|
||||
local_file)
|
||||
parsed_args = self.check_parser(
|
||||
self.download_vnf_package_artifacts, arglist, verifylist)
|
||||
self._mock_request_url_for_download_artifacts(
|
||||
local_file.name[1:], artifact_data)
|
||||
self.download_vnf_package_artifacts.take_action(parsed_args)
|
||||
self.assertTrue(filecmp.cmp(test_file, local_file.name),
|
||||
"Downloaded contents don't match test file")
|
||||
|
|
|
@ -83,7 +83,17 @@ def vnf_package_obj(attrs=None, onboarded_state=False):
|
|||
"packageContent": {
|
||||
"href": "string"
|
||||
}
|
||||
}}
|
||||
},
|
||||
"additionalArtifacts": [
|
||||
{
|
||||
"artifactPath": "string",
|
||||
"metadata": {},
|
||||
"checksum": {
|
||||
"algorithm": "string",
|
||||
"hash": "string"
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
fake_vnf_package.update(attrs)
|
||||
|
@ -102,7 +112,7 @@ def get_vnf_package_data(vnf_package_obj, **kwargs):
|
|||
'CREATED', 'DISABLED', 'NOT_IN_USE', {'Test_key': 'Test_value'}]
|
||||
"""
|
||||
complex_attributes = ['softwareImages', 'checksum', '_links',
|
||||
'userDefinedData']
|
||||
'userDefinedData', 'additionalArtifacts']
|
||||
for attribute in complex_attributes:
|
||||
if vnf_package_obj.get(attribute):
|
||||
vnf_package_obj.update(
|
||||
|
|
|
@ -229,6 +229,8 @@ class ClientBase(object):
|
|||
self.format = 'zip'
|
||||
elif 'text/plain' == resp.headers.get('Content-Type'):
|
||||
self.format = 'text'
|
||||
elif 'artifacts' in action:
|
||||
self.format = 'any'
|
||||
else:
|
||||
self.format = 'json'
|
||||
|
||||
|
@ -265,7 +267,7 @@ class ClientBase(object):
|
|||
|
||||
def deserialize(self, data, status_code):
|
||||
"""Deserializes an XML or JSON string into a dictionary."""
|
||||
if status_code in (204, 202) or self.format in ('zip', 'text'):
|
||||
if status_code in (204, 202) or self.format in ('zip', 'text', 'any'):
|
||||
return data
|
||||
return serializer.Serializer(self.get_attr_metadata()).deserialize(
|
||||
data, self.content_type())['body']
|
||||
|
@ -775,6 +777,8 @@ class VnfPackageClient(ClientBase):
|
|||
vnfpackage_path = '/vnfpkgm/v1/vnf_packages/%s'
|
||||
vnfpackage_vnfd_path = '/vnfpkgm/v1/vnf_packages/%s/vnfd'
|
||||
vnfpackage_download_path = '/vnfpkgm/v1/vnf_packages/%s/package_content'
|
||||
vnfpakcage_artifact_path = '/vnfpkgm/v1/vnf_packages/%(id)s/artifacts/' \
|
||||
'%(artifact_path)s'
|
||||
|
||||
def build_action(self, action):
|
||||
return action
|
||||
|
@ -845,6 +849,11 @@ class VnfPackageClient(ClientBase):
|
|||
self.format = 'both'
|
||||
return self.get(self.vnfpackage_vnfd_path % vnf_package)
|
||||
|
||||
@APIParamsCall
|
||||
def download_artifact_from_vnf_package(self, vnf_package, artifact_path):
|
||||
return self.get(self.vnfpakcage_artifact_path %
|
||||
{'id': vnf_package, 'artifact_path': artifact_path})
|
||||
|
||||
@APIParamsCall
|
||||
def update_vnf_package(self, vnf_package, body):
|
||||
return self.patch(self.vnfpackage_path % vnf_package, body=body)
|
||||
|
@ -1183,5 +1192,10 @@ class Client(object):
|
|||
return self.vnf_package_client.download_vnfd_from_vnf_package(
|
||||
vnf_package, accept)
|
||||
|
||||
def download_artifact_from_vnf_package(self, vnf_package, artifact_path):
|
||||
return self.vnf_package_client.download_artifact_from_vnf_package(
|
||||
vnf_package, artifact_path
|
||||
)
|
||||
|
||||
def download_vnf_package(self, vnf_package):
|
||||
return self.vnf_package_client.download_vnf_package(vnf_package)
|
||||
|
|
Loading…
Reference in New Issue