Merge branch 'master' into tosca
Signed-off-by: Hashir Mohammed <hashir.mohammed@riftio.com>
diff --git a/common/python/CMakeLists.txt b/common/python/CMakeLists.txt
index 22018c3..50ed1de 100644
--- a/common/python/CMakeLists.txt
+++ b/common/python/CMakeLists.txt
@@ -112,6 +112,10 @@
rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py
rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py
rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py
+ rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py
+ rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py
+ rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py
+ rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py
rift/mano/tosca_translator/common/__init__.py
rift/mano/tosca_translator/common/utils.py
rift/mano/tosca_translator/common/exception.py
@@ -168,6 +172,20 @@
${CMAKE_CURRENT_SOURCE_DIR}/rift/mano/yang_translator/yang-translator)
install(
+ FILES rift/mano/yang_translator/riftiotypes.yaml
+ DESTINATION
+ usr/rift/mano/common
+ COMPONENT ${PKG_LONG_NAME}
+ )
+
+install(
+ FILES rift/mano/tosca_translator/dummy_vnf_node.yaml
+ DESTINATION
+ usr/rift/mano/common
+ COMPONENT ${PKG_LONG_NAME}
+ )
+
+install(
FILES ${TRANSLATOR_SCRIPTS}
DESTINATION
usr/bin
diff --git a/common/python/rift/mano/tosca_translator/dummy_vnf_node.yaml b/common/python/rift/mano/tosca_translator/dummy_vnf_node.yaml
new file mode 100644
index 0000000..6798e2a
--- /dev/null
+++ b/common/python/rift/mano/tosca_translator/dummy_vnf_node.yaml
@@ -0,0 +1,1496 @@
+tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
+description: Toy NS
+data_types:
+ tosca.datatypes.nfv.riftio.dashboard_params:
+ properties:
+ path:
+ type: string
+ description: >-
+ The HTTP path for the dashboard
+ port:
+ type: tosca.datatypes.network.PortDef
+ description: >-
+ The HTTP port for the dashboard
+ default: 80
+ https:
+ type: boolean
+ description: >-
+ Pick HTTPS instead of HTTP , Default is false
+ default: false
+ required: false
+ tosca.datatypes.nfv.riftio.monitoring_param_ui:
+ properties:
+ description:
+ type: string
+ required: false
+ group_tag:
+ type: string
+ description: >-
+ A simple tag to group monitoring parameters
+ required: false
+ widget_type:
+ type: string
+ description: >-
+ Type of the widget
+ default: counter
+ constraints:
+ - valid_values:
+ - histogram
+ - bar
+ - gauge
+ - slider
+ - counter
+ - textbox
+ units:
+ type: string
+ required: false
+ tosca.datatypes.nfv.riftio.monitoring_param_value:
+ properties:
+ value_type:
+ type: string
+ default: integer
+ constraints:
+ - valid_values:
+ - integer
+ - float
+ - string
+ numeric_min:
+ type: integer
+ description: >-
+ Minimum value for the parameter
+ required: false
+ numeric_max:
+ type: integer
+ description: >-
+ Maxium value for the parameter
+ required: false
+ string_min:
+ type: integer
+ description: >-
+ Minimum string length for the parameter
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ string_max:
+ type: integer
+ description: >-
+ Maximum string length for the parameter
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ tosca.datatypes.compute.Container.Architecture.CPUAllocation:
+ derived_from: tosca.datatypes.Root
+ properties:
+ cpu_affinity:
+ type: string
+ required: false
+ constraints:
+ - valid_values: [shared, dedicated, any]
+ thread_allocation:
+ type: string
+ required: false
+ constraints:
+ - valid_values: [avoid, separate, isolate, prefer]
+ socket_count:
+ type: integer
+ required: false
+ core_count:
+ type: integer
+ required: false
+ thread_count:
+ type: integer
+ required: false
+
+ tosca.datatypes.compute.Container.Architecture.NUMA:
+ derived_from: tosca.datatypes.Root
+ properties:
+ id:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ vcpus:
+ type: list
+ entry_schema:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ mem_size:
+ type: scalar-unit.size
+ constraints:
+ - greater_or_equal: 0 MB
+ tosca.datatypes.nfv.riftio.paired_thread_map:
+ properties:
+ thread_a:
+ type: integer
+ required: true
+ constraints:
+ - greater_or_equal: 0
+ thread_b:
+ type: integer
+ required: true
+ constraints:
+ - greater_or_equal: 0
+
+ tosca.datatypes.nfv.riftio.paired_threads:
+ properties:
+ num_paired_threads:
+ type: integer
+ constraints:
+ - greater_or_equal: 1
+ paired_thread_ids:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.nfv.riftio.paired_thread_map
+ constraints:
+ - max_length: 16
+ required: false
+
+ tosca.datatypes.compute.riftio.numa:
+ properties:
+ id:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ vcpus:
+ type: list
+ entry_schema:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ mem_size:
+ type: scalar-unit.size
+ constraints:
+ - greater_or_equal: 0 MB
+ required: false
+ om_numa_type:
+ type: string
+ description: Openmano Numa type selection
+ constraints:
+ - valid_values: [cores, paired-threads, threads]
+ required: false
+ num_cores:
+ type: integer
+ description: Use when om_numa_type is cores
+ constraints:
+ - greater_or_equal: 1
+ required: false
+ paired_threads:
+ type: tosca.datatypes.nfv.riftio.paired_threads
+ description: Use when om_numa_type is paired-threads
+ required: false
+ num_threads:
+ type: integer
+ description: Use when om_numa_type is threads
+ constraints:
+ - greater_or_equal: 1
+ required: false
+
+ tosca.nfv.datatypes.pathType:
+ properties:
+ forwarder:
+ type: string
+ required: true
+ capability:
+ type: string
+ required: true
+
+ tosca.nfv.datatypes.aclType:
+ properties:
+ eth_type:
+ type: string
+ required: false
+ eth_src:
+ type: string
+ required: false
+ eth_dst:
+ type: string
+ required: false
+ vlan_id:
+ type: integer
+ constraints:
+ - in_range: [ 1, 4094 ]
+ required: false
+ vlan_pcp:
+ type: integer
+ constraints:
+ - in_range: [ 0, 7 ]
+ required: false
+ mpls_label:
+ type: integer
+ constraints:
+ - in_range: [ 16, 1048575]
+ required: false
+ mpls_tc:
+ type: integer
+ constraints:
+ - in_range: [ 0, 7 ]
+ required: false
+ ip_dscp:
+ type: integer
+ constraints:
+ - in_range: [ 0, 63 ]
+ required: false
+ ip_ecn:
+ type: integer
+ constraints:
+ - in_range: [ 0, 3 ]
+ required: false
+ ip_src_prefix:
+ type: string
+ required: false
+ ip_dst_prefix:
+ type: string
+ required: false
+ ip_proto:
+ type: integer
+ constraints:
+ - in_range: [ 1, 254 ]
+ required: false
+ destination_port_range:
+ type: string
+ required: false
+ source_port_range:
+ type: string
+ required: false
+ network_src_port_id:
+ type: string
+ required: false
+ network_dst_port_id:
+ type: string
+ required: false
+ network_id:
+ type: string
+ required: false
+ network_name:
+ type: string
+ required: false
+ tenant_id:
+ type: string
+ required: false
+ icmpv4_type:
+ type: integer
+ constraints:
+ - in_range: [ 0, 254 ]
+ required: false
+ icmpv4_code:
+ type: integer
+ constraints:
+ - in_range: [ 0, 15 ]
+ required: false
+ arp_op:
+ type: integer
+ constraints:
+ - in_range: [ 1, 25 ]
+ required: false
+ arp_spa:
+ type: string
+ required: false
+ arp_tpa:
+ type: string
+ required: false
+ arp_sha:
+ type: string
+ required: false
+ arp_tha:
+ type: string
+ required: false
+ ipv6_src:
+ type: string
+ required: false
+ ipv6_dst:
+ type: string
+ required: false
+ ipv6_flabel:
+ type: integer
+ constraints:
+ - in_range: [ 0, 1048575]
+ required: false
+ icmpv6_type:
+ type: integer
+ constraints:
+ - in_range: [ 0, 255]
+ required: false
+ icmpv6_code:
+ type: integer
+ constraints:
+ - in_range: [ 0, 7]
+ required: false
+ ipv6_nd_target:
+ type: string
+ required: false
+ ipv6_nd_sll:
+ type: string
+ required: false
+ ipv6_nd_tll:
+ type: string
+ required: false
+
+
+ tosca.datatypes.nfv.riftio.vnf_configuration:
+ properties:
+ config_type:
+ type: string
+ description: >-
+ Type of the configuration agent to use
+ constraints:
+ - valid_values: [script, netconf, rest, juju]
+ config_details:
+ type: map
+ description: >-
+ Specify the details for the config agent, like
+ script type, juju charm to use, etc.
+ config_template:
+ required: false
+ type: string
+ config_delay:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ default: 0
+ required: false
+ config_priority:
+ type: integer
+ constraints:
+ - greater_than: 0
+
+ tosca.datatypes.nfv.riftio.parameter_value:
+ properties:
+ name:
+ type: string
+ description: Name of the parameter
+ value:
+ type: string
+ description: Value of the parameter
+
+ tosca.datatypes.nfv.riftio.config_primitive:
+ properties:
+ name:
+ type: string
+ seq:
+ type: integer
+ description: >-
+ Order in which to apply, when multiple ones are defined
+ default: 0
+ constraints:
+ - greater_or_equal: 0
+ parameter:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.nfv.riftio.parameter_value
+ user_defined_script:
+ type: string
+ tosca.datatypes.nfv.riftio.primitive_parameter:
+ properties:
+ data_type:
+ type: string
+ description: >-
+ Data type associated with the name
+ constraints:
+ - valid_values: [string, integer, boolean]
+ mandatory:
+ type: boolean
+ description: >-
+ If this field is mandatory
+ default: false
+ required: false
+ default_value:
+ type: string
+ description: >-
+ The default value for this field
+ required: false
+ parameter_pool:
+ type: string
+ description: >-
+ Parameter pool name to use for this parameter
+ required: false
+ read_only:
+ type: boolean
+ description: >-
+ The value should be greyed out by the UI.
+ Only applies to parameters with default values.
+ required: false
+ default: false
+ hidden:
+ type: boolean
+ description: >-
+ The field should be hidden by the UI.
+ Only applies to parameters with default values.
+ required: false
+ default: false
+ tosca.datatypes.nfv.riftio.primitive_parameter_group:
+ properties:
+ name:
+ type: string
+ description: >-
+ Name of the parameter group
+ mandatory:
+ type: boolean
+ description: >-
+ If this group is mandatory
+ default: false
+ required: false
+ parameter:
+ type: map
+ description: >-
+ List of parameters for the service primitive
+ entry_schema: osca.datatypes.riftio.primitive_parameter
+
+ tosca.datatypes.nfv.riftio.vnf_primitive_group:
+ properties:
+ vnf_name:
+ type: string
+ description: >-
+ Name of the VNF in the NS
+ primitive:
+ type: map
+ entry_schema:
+ type: string
+ description: >-
+ Index and name of the primitive
+
+
+capability_types:
+ tosca.capabilities.nfv.riftio.mgmt_interface:
+ derived_from: tosca.capabilities.Endpoint
+ properties:
+ static_ip:
+ type: string
+ required: false
+ description: >-
+ Specifies the static IP address for managing the VNF
+ connection_point:
+ type: string
+ required: false
+ description: >-
+ Use the ip address associated with this connection point
+ dashboard_params:
+ type: tosca.datatypes.nfv.riftio.dashboard_params
+ required: false
+ description: >-
+ Parameters for the VNF dashboard
+ tosca.capabilities.nfv.riftio.monitoring_param:
+ derived_from: tosca.capabilities.nfv.Metric
+ properties:
+ name:
+ type: string
+ required: false
+ description:
+ type: string
+ required: false
+ protocol:
+ type: string
+ default: http
+ constraints:
+ - equal: http
+ polling_interval:
+ type: scalar-unit.time
+ description: >-
+ The HTTP polling interval in seconds
+ default: 2 s
+ username:
+ type: string
+ description: >-
+ The HTTP basic auth username
+ required: false
+ password:
+ type: string
+ description: >-
+ The HTTP basic auth password
+ required: false
+ method:
+ type: string
+ description: >-
+ This is the method to be performed at the uri.
+ GET by default for action
+ default: get
+ constraints:
+ - valid_values: [post, put, get, delete, options, patch]
+ headers:
+ type: map
+ entry_schema:
+ type: string
+ description: >-
+ Custom HTTP headers to put on HTTP request
+ required: false
+ json_query_method:
+ type: string
+ description: >-
+ The method to extract a value from a JSON response
+ namekey - Use the name as the key for a non-nested value.
+ jsonpath - Use jsonpath-rw implemenation to extract a value.
+ objectpath - Use objectpath implemenation to extract a value.
+ constraints:
+ - valid_values: [namekey, jsonpath, objectpath]
+ default: namekey
+ json_query_path:
+ type: string
+ description: >-
+ The json path to use to extract value from JSON structure
+ required: false
+ json_object_path:
+ type: string
+ description: >-
+ The object path to use to extract value from JSON structure
+ required: false
+ ui_data:
+ type: tosca.datatypes.nfv.riftio.monitoring_param_ui
+ required: false
+ constraints:
+ type: tosca.datatypes.nfv.riftio.monitoring_param_value
+ required: false
+ tosca.capabilities.nfv.riftio.numa_extension:
+ derived_from: tosca.capabilities.Root
+ properties:
+ node_cnt:
+ type: integer
+ description: >-
+ The number of numa nodes to expose to the VM
+ constraints:
+ - greater_or_equal: 0
+ mem_policy:
+ type: string
+ description: >-
+ This policy specifies how the memory should
+ be allocated in a multi-node scenario.
+ STRICT - The memory must be allocated
+ strictly from the memory attached
+ to the NUMA node.
+ PREFERRED - The memory should be allocated
+ preferentially from the memory
+ attached to the NUMA node
+ constraints:
+ - valid_values: [strict, preferred, STRICT, PREFERRED]
+ node:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.compute.riftio.numa
+ tosca.capabilities.nfv.riftio.vswitch_epa:
+ derived_from: tosca.capabilities.Root
+ properties:
+ ovs_acceleration:
+ type: string
+ description: |-
+ Specifies Open vSwitch acceleration mode.
+ MANDATORY - OVS acceleration is required
+ PREFERRED - OVS acceleration is preferred
+ constraints:
+ - valid_values: [mandatory, preferred, disabled, MANDATORY, PREFERRED, DISABLED]
+ ovs_offload:
+ type: string
+ description: |-
+ Specifies Open vSwitch hardware offload mode.
+ MANDATORY - OVS offload is required
+ PREFERRED - OVS offload is preferred
+ constraints:
+ - valid_values: [mandatory, preferred, disabled, MANDATORY, PREFERRED, DISABLED]
+
+ tosca.capabilities.nfv.riftio.hypervisor_epa:
+ derived_from: tosca.capabilities.Root
+ properties:
+ type:
+ type: string
+ description: |-
+ Specifies the type of hypervisor.
+ constraints:
+ - valid_values: [prefer_kvm, require_kvm, PREFER_KVM, REQUIRE_KVM]
+ version:
+ type: string
+
+ tosca.capabilities.nfv.riftio.host_epa:
+ derived_from: tosca.capabilities.Root
+ properties:
+ cpu_model:
+ type: string
+ description: >-
+ Host CPU model. Examples include SandyBridge,
+ IvyBridge, etc.
+ required: false
+ constraints:
+ - valid_values:
+ - prefer_westmere
+ - require_westmere
+ - prefer_sandbridge
+ - require_sandybridge
+ - prefer_ivybridge
+ - require_ivybridge
+ - prefer_haswell
+ - require_haswell
+ - prefer_broadwell
+ - require_broadwell
+ - prefer_nehalem
+ - require_nehalem
+ - prefer_penryn
+ - require_penryn
+ - prefer_conroe
+ - require_conroe
+ - prefer_core2duo
+ - require_core2duo
+ - PREFER_WESTMERE
+ - REQUIRE_WESTMERE
+ - PREFER_SANDBRIDGE
+ - REQUIRE_SANDYBRIDGE
+ - PREFER_IVYBRIDGE
+ - REQUIRE_IVYBRIDGE
+ - PREFER_HASWELL
+ - REQUIRE_HASWELL
+ - PREFER_BROADWELL
+ - REQUIRE_BROADWELL
+ - PREFER_NEHALEM
+ - REQUIRE_NEHALEM
+ - PREFER_PENRYN
+ - REQUIRE_PENRYN
+ - PREFER_CONROE
+ - REQUIRE_CONROE
+ - PREFER_CORE2DUO
+ - REQUIRE_CORE2DUO
+ cpu_arch:
+ type: string
+ description: >-
+ Host CPU architecture
+ required: false
+ constraints:
+ - valid_values:
+ - prefer_x86
+ - require_x86
+ - prefer_x86_64
+ - require_x86_64
+ - prefer_i686
+ - require_i686
+ - prefer_ia64
+ - require_ia64
+ - prefer_armv7
+ - require_armv7
+ - prefer_armv8
+ - require_armv8
+ - PREFER_X86
+ - REQUIRE_X86
+ - PREFER_X86_64
+ - REQUIRE_X86_64
+ - PREFER_I686
+ - REQUIRE_I686
+ - PREFER_IA64
+ - REQUIRE_IA64
+ - PREFER_ARMV7
+ - REQUIRE_ARMV7
+ - PREFER_ARMV8
+ - REQUIRE_ARMV8
+ cpu_vendor:
+ type: string
+ description: >-
+ Host CPU vendor
+ required: false
+ constraints:
+ - valid_values:
+ - prefer_intel
+ - require_intel
+ - prefer_amd
+ - requie_amd
+ - PREFER_INTEL
+ - REQUIRE_INTEL
+ - PREFER_AMD
+ - REQUIE_AMD
+ cpu_socket_count:
+ type: integer
+ description: >-
+ Number of sockets on the host
+ required: false
+ constraints:
+ - greater_than : 0
+ cpu_core_count:
+ type: integer
+ description: >-
+ Number of cores on the host
+ required: false
+ constraints:
+ - greater_than : 0
+ cpu_core_thread_count:
+ type: integer
+ description: >-
+ Number of threads per core on the host
+ required: false
+ constraints:
+ - greater_than : 0
+ cpu_feature:
+ type: list
+ entry_schema:
+ type: string
+ description: |-
+ Enumeration for CPU features.
+
+ AES- CPU supports advanced instruction set for
+ AES (Advanced Encryption Standard).
+
+ CAT- Cache Allocation Technology (CAT) allows
+ an Operating System, Hypervisor, or similar
+ system management agent to specify the amount
+ of L3 cache (currently the last-level cache
+ in most server and client platforms) space an
+ application can fill (as a hint to hardware
+ functionality, certain features such as power
+ management may override CAT settings).
+
+ CMT- Cache Monitoring Technology (CMT) allows
+ an Operating System, Hypervisor, or similar
+ system management agent to determine the
+ usage of cache based on applications running
+ on the platform. The implementation is
+ directed at L3 cache monitoring (currently
+ the last-level cache in most server and
+ client platforms).
+
+ DDIO- Intel Data Direct I/O (DDIO) enables
+ Ethernet server NICs and controllers talk
+ directly to the processor cache without a
+ detour via system memory. This enumeration
+ specifies if the VM requires a DDIO
+ capable host.
+ required: false
+ constraints:
+ -valid_values:
+ - prefer_aes
+ - require_aes
+ - prefer_cat
+ - require_cat
+ - prefer_cmt
+ - require_cmt
+ - prefer_ddio
+ - require_ddio
+ - prefer_vme
+ - require_vme
+ - prefer_de
+ - require_de
+ - prefer_pse
+ - require_pse
+ - prefer_tsc
+ - require_tsc
+ - prefer_msr
+ - require_msr
+ - prefer_pae
+ - require_pae
+ - prefer_mce
+ - require_mce
+ - prefer_cx8
+ - require_cx8
+ - prefer_apic
+ - require_apic
+ - prefer_sep
+ - require_sep
+ - prefer_mtrr
+ - require_mtrr
+ - prefer_pge
+ - require_pge
+ - prefer_mca
+ - require_mca
+ - prefer_cmov
+ - require_cmov
+ - prefer_pat
+ - require_pat
+ - prefer_pse36
+ - require_pse36
+ - prefer_clflush
+ - require_clflush
+ - prefer_dts
+ - require_dts
+ - prefer_acpi
+ - require_acpi
+ - prefer_mmx
+ - require_mmx
+ - prefer_fxsr
+ - require_fxsr
+ - prefer_sse
+ - require_sse
+ - prefer_sse2
+ - require_sse2
+ - prefer_ss
+ - require_ss
+ - prefer_ht
+ - require_ht
+ - prefer_tm
+ - require_tm
+ - prefer_ia64
+ - require_ia64
+ - prefer_pbe
+ - require_pbe
+ - prefer_rdtscp
+ - require_rdtscp
+ - prefer_pni
+ - require_pni
+ - prefer_pclmulqdq
+ - require_pclmulqdq
+ - prefer_dtes64
+ - require_dtes64
+ - prefer_monitor
+ - require_monitor
+ - prefer_ds_cpl
+ - require_ds_cpl
+ - prefer_vmx
+ - require_vmx
+ - prefer_smx
+ - require_smx
+ - prefer_est
+ - require_est
+ - prefer_tm2
+ - require_tm2
+ - prefer_ssse3
+ - require_ssse3
+ - prefer_cid
+ - require_cid
+ - prefer_fma
+ - require_fma
+ - prefer_cx16
+ - require_cx16
+ - prefer_xtpr
+ - require_xtpr
+ - prefer_pdcm
+ - require_pdcm
+ - prefer_pcid
+ - require_pcid
+ - prefer_dca
+ - require_dca
+ - prefer_sse4_1
+ - require_sse4_1
+ - prefer_sse4_2
+ - require_sse4_2
+ - prefer_x2apic
+ - require_x2apic
+ - prefer_movbe
+ - require_movbe
+ - prefer_popcnt
+ - require_popcnt
+ - prefer_tsc_deadline_timer
+ - require_tsc_deadline_timer
+ - prefer_xsave
+ - require_xsave
+ - prefer_avx
+ - require_avx
+ - prefer_f16c
+ - require_f16c
+ - prefer_rdrand
+ - require_rdrand
+ - prefer_fsgsbase
+ - require_fsgsbase
+ - prefer_bmi1
+ - require_bmi1
+ - prefer_hle
+ - require_hle
+ - prefer_avx2
+ - require_avx2
+ - prefer_smep
+ - require_smep
+ - prefer_bmi2
+ - require_bmi2
+ - prefer_erms
+ - require_erms
+ - prefer_invpcid
+ - require_invpcid
+ - prefer_rtm
+ - require_rtm
+ - prefer_mpx
+ - require_mpx
+ - prefer_rdseed
+ - require_rdseed
+ - prefer_adx
+ - require_adx
+ - prefer_smap
+ - require_smap
+ - PREFER_AES
+ - REQUIRE_AES
+ - PREFER_CAT
+ - REQUIRE_CAT
+ - PREFER_CMT
+ - REQUIRE_CMT
+ - PREFER_DDIO
+ - REQUIRE_DDIO
+ - PREFER_VME
+ - REQUIRE_VME
+ - PREFER_DE
+ - REQUIRE_DE
+ - PREFER_PSE
+ - REQUIRE_PSE
+ - PREFER_TSC
+ - REQUIRE_TSC
+ - PREFER_MSR
+ - REQUIRE_MSR
+ - PREFER_PAE
+ - REQUIRE_PAE
+ - PREFER_MCE
+ - REQUIRE_MCE
+ - PREFER_CX8
+ - REQUIRE_CX8
+ - PREFER_APIC
+ - REQUIRE_APIC
+ - PREFER_SEP
+ - REQUIRE_SEP
+ - PREFER_MTRR
+ - REQUIRE_MTRR
+ - PREFER_PGE
+ - REQUIRE_PGE
+ - PREFER_MCA
+ - REQUIRE_MCA
+ - PREFER_CMOV
+ - REQUIRE_CMOV
+ - PREFER_PAT
+ - REQUIRE_PAT
+ - PREFER_PSE36
+ - REQUIRE_PSE36
+ - PREFER_CLFLUSH
+ - REQUIRE_CLFLUSH
+ - PREFER_DTS
+ - REQUIRE_DTS
+ - PREFER_ACPI
+ - REQUIRE_ACPI
+ - PREFER_MMX
+ - REQUIRE_MMX
+ - PREFER_FXSR
+ - REQUIRE_FXSR
+ - PREFER_SSE
+ - REQUIRE_SSE
+ - PREFER_SSE2
+ - REQUIRE_SSE2
+ - PREFER_SS
+ - REQUIRE_SS
+ - PREFER_HT
+ - REQUIRE_HT
+ - PREFER_TM
+ - REQUIRE_TM
+ - PREFER_IA64
+ - REQUIRE_IA64
+ - PREFER_PBE
+ - REQUIRE_PBE
+ - PREFER_RDTSCP
+ - REQUIRE_RDTSCP
+ - PREFER_PNI
+ - REQUIRE_PNI
+ - PREFER_PCLMULQDQ
+ - REQUIRE_PCLMULQDQ
+ - PREFER_DTES64
+ - REQUIRE_DTES64
+ - PREFER_MONITOR
+ - REQUIRE_MONITOR
+ - PREFER_DS_CPL
+ - REQUIRE_DS_CPL
+ - PREFER_VMX
+ - REQUIRE_VMX
+ - PREFER_SMX
+ - REQUIRE_SMX
+ - PREFER_EST
+ - REQUIRE_EST
+ - PREFER_TM2
+ - REQUIRE_TM2
+ - PREFER_SSSE3
+ - REQUIRE_SSSE3
+ - PREFER_CID
+ - REQUIRE_CID
+ - PREFER_FMA
+ - REQUIRE_FMA
+ - PREFER_CX16
+ - REQUIRE_CX16
+ - PREFER_XTPR
+ - REQUIRE_XTPR
+ - PREFER_PDCM
+ - REQUIRE_PDCM
+ - PREFER_PCID
+ - REQUIRE_PCID
+ - PREFER_DCA
+ - REQUIRE_DCA
+ - PREFER_SSE4_1
+ - REQUIRE_SSE4_1
+ - PREFER_SSE4_2
+ - REQUIRE_SSE4_2
+ - PREFER_X2APIC
+ - REQUIRE_X2APIC
+ - PREFER_MOVBE
+ - REQUIRE_MOVBE
+ - PREFER_POPCNT
+ - REQUIRE_POPCNT
+ - PREFER_TSC_DEADLINE_TIMER
+ - REQUIRE_TSC_DEADLINE_TIMER
+ - PREFER_XSAVE
+ - REQUIRE_XSAVE
+ - PREFER_AVX
+ - REQUIRE_AVX
+ - PREFER_F16C
+ - REQUIRE_F16C
+ - PREFER_RDRAND
+ - REQUIRE_RDRAND
+ - PREFER_FSGSBASE
+ - REQUIRE_FSGSBASE
+ - PREFER_BMI1
+ - REQUIRE_BMI1
+ - PREFER_HLE
+ - REQUIRE_HLE
+ - PREFER_AVX2
+ - REQUIRE_AVX2
+ - PREFER_SMEP
+ - REQUIRE_SMEP
+ - PREFER_BMI2
+ - REQUIRE_BMI2
+ - PREFER_ERMS
+ - REQUIRE_ERMS
+ - PREFER_INVPCID
+ - REQUIRE_INVPCID
+ - PREFER_RTM
+ - REQUIRE_RTM
+ - PREFER_MPX
+ - REQUIRE_MPX
+ - PREFER_RDSEED
+ - REQUIRE_RDSEED
+ - PREFER_ADX
+ - REQUIRE_ADX
+ - PREFER_SMAP
+ - REQUIRE_SMAP
+ om_cpu_model_string:
+ type: string
+ description: >-
+ Openmano CPU model string
+ required: false
+ om_cpu_feature:
+ type: list
+ entry_schema:
+ type: string
+ description: >-
+ List of openmano CPU features
+ required: false
+
+ tosca.capabilities.nfv.riftio.sfc:
+ derived_from: tosca.capabilities.Root
+ description: >-
+ Service Function Chaining support on this VDU
+ properties:
+ sfc_type:
+ type: string
+ description: >-
+ Type of node in Service Function Chaining Architecture
+ constraints:
+ - valid_values: [unaware, classifier, sf, sff, UNAWARE, CLASSIFIER, SF, SFF]
+ default: unaware
+ sf_type:
+ type: string
+ description: >-
+ Type of Service Function.
+ NOTE- This needs to map with Service Function Type in ODL to
+ support VNFFG. Service Function Type is manadatory param in ODL
+ SFC.
+ required: false
+ tosca.capabilities.Compute.Container.Architecture:
+ derived_from: tosca.capabilities.Container
+ properties:
+ mem_page_size:
+ type: string
+ description: >-
+ Memory page allocation size. If a VM requires
+ hugepages, it should choose huge or size_2MB
+ or size_1GB. If the VM prefers hugepages, it
+ should chose prefer_huge.
+ huge - Require hugepages (either 2MB or 1GB)
+ normal - Does not require hugepages
+ size_2MB - Requires 2MB hugepages
+ size_1GB - Requires 1GB hugepages
+ prefer_huge - Application perfers hugepages
+ NOTE - huge and normal is only defined in standards as of
+ now.
+ required: false
+ constraints:
+ - valid_values: [normal, huge, size_2MB, size_1GB, prefer_huge, NORMAL, HUGE, SIZE_2MB, SIZE_1GB, PREFER_HUGE]
+ cpu_allocation:
+ type: tosca.datatypes.compute.Container.Architecture.CPUAllocation
+ required: false
+ numa_nodes:
+ type: map
+ required: false
+ entry_schema:
+ type: tosca.datatypes.compute.Container.Architecture.NUMA
+
+
+node_types:
+ tosca.nodes.nfv.riftio.VDU1:
+ derived_from: tosca.nodes.nfv.VDU
+ properties:
+ description:
+ type: string
+ required: false
+ image:
+ description: >-
+ If an image is specified here, it is assumed that the image
+ is already present in the RO or VIM and not in the package.
+ type: string
+ required: false
+ image_checksum:
+ type: string
+ description: >-
+ Image checksum for the image in RO or VIM.
+ required: false
+ cloud_init:
+ description: >-
+ Inline cloud-init specification
+ required: false
+ type: string
+ count:
+ default: 1
+ type: integer
+ capabilities:
+ virtualLink:
+ type: tosca.capabilities.nfv.VirtualLinkable
+ monitoring_param_1:
+ type: tosca.capabilities.nfv.riftio.monitoring_param
+ mgmt_interface:
+ type: tosca.capabilities.nfv.riftio.mgmt_interface
+ monitoring_param:
+ type: tosca.capabilities.nfv.riftio.monitoring_param
+ numa_extension:
+ type: tosca.capabilities.nfv.riftio.numa_extension
+ vswitch_epa:
+ type: tosca.capabilities.nfv.riftio.vswitch_epa
+ hypervisor_epa:
+ type: tosca.capabilities.nfv.riftio.hypervisor_epa
+ host_epa:
+ type: tosca.capabilities.nfv.riftio.host_epa
+ tosca.nodes.nfv.riftio.CP1:
+ derived_from: tosca.nodes.nfv.CP
+ properties:
+ cp_type:
+ description: Type of the connection point
+ type: string
+ default: VPORT
+ constraints:
+ - valid_values: [VPORT]
+ name:
+ description: Name of the connection point
+ type: string
+ required: false
+ vdu_intf_name:
+ description: Name of the interface on VDU
+ type: string
+ vdu_intf_type:
+ description: >-
+ Specifies the type of virtual interface
+ between VM and host.
+ VIRTIO - Use the traditional VIRTIO interface.
+ PCI-PASSTHROUGH - Use PCI-PASSTHROUGH interface.
+ SR-IOV - Use SR-IOV interface.
+ E1000 - Emulate E1000 interface.
+ RTL8139 - Emulate RTL8139 interface.
+ PCNET - Emulate PCNET interface.
+ OM-MGMT - Used to specify openmano mgmt external-connection type
+ type: string
+ constraints:
+ - valid_values: [OM-MGMT, VIRTIO, E1000, SR-IOV]
+ bandwidth:
+ type: integer
+ description: Aggregate bandwidth of the NIC
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ vpci:
+ type: string
+ description: >-
+ Specifies the virtual PCI address. Expressed in
+ the following format dddd:dd:dd.d. For example
+ 0000:00:12.0. This information can be used to
+ pass as metadata during the VM creation.
+ required: false
+ capabilities:
+ sfc:
+ type: tosca.capabilities.nfv.riftio.sfc
+ tosca.nodes.nfv.riftio.VNF1:
+ derived_from: tosca.nodes.nfv.VNF
+ properties:
+ member_index:
+ type: integer
+ constraints:
+ - greater_or_equal: 1
+ description: Index of the VNF in the NS
+ required: false
+ start_by_default:
+ type: boolean
+ default: true
+ description: Start this VNF on NS instantiate
+ logo:
+ type: string
+ description: >-
+ Logo to display with the VNF in the orchestrator
+ required: false
+ capabilities:
+ mgmt_interface:
+ type: tosca.capabilities.nfv.riftio.mgmt_interface
+ monitoring_param:
+ type: tosca.capabilities.nfv.riftio.monitoring_param
+ sfc:
+ type: tosca.capabilities.nfv.riftio.sfc
+ tosca.nodes.nfv.riftio.ELAN:
+ derived_from: tosca.nodes.nfv.VL.ELAN
+ properties:
+ description:
+ type: string
+ required: false
+ network_name:
+ type: string
+ description: >-
+ Name of network in VIM account. This is used to indicate
+ pre-provisioned network name in cloud account.
+ required: false
+ root_bandwidth:
+ type: integer
+ description: >-
+ This is the aggregate bandwidth
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ leaf_bandwidth:
+ type: integer
+ description: >-
+ This is the bandwidth of branches
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ tosca.nodes.nfv.riftio.FP1:
+ derived_from: tosca.nodes.nfv.FP
+ properties:
+ id:
+ type: integer
+ required: false
+ policy:
+ type: tosca.nfv.datatypes.policyType
+ required: true
+ description: policy to use to match traffic for this FP
+ path:
+ type: list
+ required: true
+ entry_schema:
+ type: tosca.nfv.datatypes.pathType
+ cp:
+ type: tosca.nfv.datatypes.pathType
+ required: true
+
+
+
+artifact_types:
+ tosca.artifacts.Deployment.riftio.cloud_init_file:
+ derived_from: tosca.artifacts.Deployment
+ file:
+ type: string
+
+ tosca.artifacts.Deployment.Image.riftio.QCOW2:
+ derived_from: tosca.artifacts.Deployment.Image.VM.QCOW2
+ image_checksum:
+ required: false
+ type: string
+
+group_types:
+ tosca.groups.nfv.VNFFG:
+ derived_from: tosca.groups.Root
+ properties:
+ vendor:
+ type: string
+ required: true
+ description: name of the vendor who generate this VNFFG
+ version:
+ type: string
+ required: true
+ description: version of this VNFFG
+ number_of_endpoints:
+ type: integer
+ required: true
+ description: count of the external endpoints included in this VNFFG
+ dependent_virtual_link:
+ type: list
+ entry_schema:
+ type: string
+ required: true
+ description: Reference to a VLD used in this Forwarding Graph
+ connection_point:
+ type: list
+ entry_schema:
+ type: string
+ required: true
+ description: Reference to Connection Points forming the VNFFG
+ constituent_vnfs:
+ type: list
+ entry_schema:
+ type: string
+ required: true
+ description: Reference to a list of VNFD used in this VNF Forwarding Graph
+ members: [ tosca.nodes.nfv.FP ]
+
+ tosca.groups.nfv.riftio.scaling:
+ derived_from: tosca.groups.Root
+ properties:
+ name:
+ type: string
+ min_instances:
+ type: integer
+ description: >-
+ Minimum instances of the scaling group which are allowed.
+ These instances are created by default when the network service
+ is instantiated.
+ max_instances:
+ type: integer
+ description: >-
+ Maximum instances of this scaling group that are allowed
+ in a single network service. The network service scaling
+ will fail, when the number of service group instances
+ exceed the max-instance-count specified.
+ cooldown_time:
+ type: integer
+ description: >-
+ The duration after a scaling-in/scaling-out action has been
+ triggered, for which there will be no further optional
+ ratio:
+ type: map
+ entry_schema:
+ type: integer
+ description: >-
+ Specify the number of instances of each VNF to instantiate
+ for a scaling action
+ members: [tosca.nodes.nfv.VNF]
+ interfaces:
+ action:
+ type: tosca.interfaces.nfv.riftio.scaling.action
+
+interface_types:
+ tosca.interfaces.nfv.riftio.scaling.action:
+ pre_scale_in:
+ description: Operation to execute before a scale in
+ post_scale_in:
+ description: Operation to execute after a scale in
+ pre_scale_out:
+ description: Operation to execute before a scale out
+ post_scale_out:
+ description: Operation to execute after a scale out
+
+policy_types:
+ tosca.policies.nfv.riftio.placement:
+ derived_from: tosca.policies.Placement
+ properties:
+ name:
+ type: string
+ description: >-
+ Place group construct to define the compute resource placement strategy
+ in cloud environment
+ requirement:
+ type: string
+ description: >-
+ This is free text space used to describe the intent/rationale
+ behind this placement group. This is for human consumption only
+ strategy:
+ type: string
+ description: >-
+ Strategy associated with this placement group
+ Following values are possible
+ COLOCATION - Colocation strategy imply intent to share the physical
+ infrastructure (hypervisor/network) among all members
+ of this group.
+ ISOLATION - Isolation strategy imply intent to not share the physical
+ infrastructure (hypervisor/network) among the members
+ of this group.
+ constraints:
+ valid_values:
+ - COLOCATION
+ - ISOLATION
+ tosca.policies.nfv.riftio.vnf_configuration:
+ derived_from: tosca.policies.Root
+ properties:
+ config:
+ type: tosca.datatypes.nfv.riftio.vnf_configuration
+ initial_config:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.nfv.riftio.config_primitive
+ tosca.policies.nfv.riftio.vnf_service_primitives:
+ derived_from: tosca.policies.Root
+ properties:
+ parameter:
+ type: map
+ entry_schema:
+ type: primitive_parameter
+ tosca.policies.nfv.riftio.ns_service_primitives:
+ derived_from: tosca.policies.Root
+ properties:
+ parameter:
+ type: map
+ entry_schema:
+ type: primitive_parameter
+ parameter_group:
+ type: tosca.datatypes.nfv.riftio.primitive_parameter_group
+ description: >-
+ Grouping of parameters which are logically grouped in UI
+ required: false
+ vnf_primitive_group:
+ type: tosca.datatypes.nfv.riftio.vnf_primitive_group
+ description: >-
+ List of service primitives grouped by VNF
+ required: false
+ user_defined_script:
+ type: string
+ description: >-
+ A user defined script
+ required: false
+ tosca.policies.nfv.riftio.initial_config_primitive:
+ derived_from: tosca.policies.Root
+ properties:
+ name:
+ type: string
+ seq:
+ type: integer
+ description: >-
+ Order in which to apply, when multiple ones are defined
+ default: 0
+ constraints:
+ - greater_or_equal: 0
+ parameter:
+ type: map
+ entry_schema:
+ type: string
+ user_defined_script:
+ type: string
+ tosca.policies.nfv.riftio.users:
+ derived_from: tosca.policies.Root
+ description: >-
+ Specify list of public keys to be injected as
+ part of NS instantitation. Use default as entry,
+ to specify the key pairs for default user.
+ properties:
+ user_info:
+ type: string
+ description: >-
+ The user\'s real name
+ required: false
+ key_pairs:
+ type: map
+ description: >-
+ List of public keys for the user
+ entry_schema:
+ type: string
+ required: true
+ tosca.policies.nfv.riftio.dependency:
+ derived_from: tosca.policies.Root
+ description: >-
+ Map dependency between VDUs or VNFs
+ properties:
+ parameter:
+ type: map
+ entry_schema:
+ type: string
+ description: >-
+ Parameter and value for the config
+ tosca.nfv.datatypes.policyType:
+ properties:
+ type:
+ type: string
+ required: false
+ constraints:
+ - valid_values: [ ACL ]
+ criteria:
+ type: list
+ required: true
+ entry_schema:
+ type: tosca.nfv.datatypes.aclType
+topology_template:
+ node_templates:
+ new_vnfd:
+ type: tosca.nodes.nfv.riftio.VNF1
+ properties:
+ id: 2
+ vendor: RIFT.io
+ version: 1.0
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py
index 2b244d7..7938485 100755
--- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_compute.py
@@ -39,7 +39,23 @@
'cloud-init-file',]
IGNORE_PROPS = []
- toscatype = 'tosca.nodes.Compute'
+ toscatype = 'tosca.nodes.nfv.VDU'
+
+ VALUE_TYPE_CONVERSION_MAP = {
+ 'integer': 'INT',
+ 'string':'STRING',
+ 'float':'DECIMAL'
+ }
+
+
+ TOSCA_MEM_SIZE = {
+ 'huge': 'LARGE',
+ 'normal': 'SMALL',
+ 'size_2MB': 'SIZE_2MB',
+ 'size_1GB': 'SIZE_1GB',
+ 'prefer_huge': 'PREFER_LARGE'
+
+ }
def __init__(self, log, nodetemplate, metadata=None):
super(ToscaCompute, self).__init__(log,
@@ -54,6 +70,9 @@
self._vnf = None
self._yang = None
self._id = self.name
+ self._monitor_param = []
+ self._mgmt_interface = {}
+ self._http_endpoint = None
@property
def image(self):
@@ -104,6 +123,39 @@
def handle_capabilities(self):
+ def get_mgmt_interface(specs):
+ mgmt_intfce = {}
+ mgmt_intfce['vdu-id'] = self.id
+ if 'dashboard_params' in specs:
+ mgmt_intfce['dashboard-params'] = {'path':specs['dashboard_params']['path'], 'port':specs['dashboard_params']['port']}
+ if 'port' in specs:
+ mgmt_intfce['port'] = specs['port']
+ return mgmt_intfce;
+
+ def get_monitor_param(specs, monitor_id):
+ monitor_param = {}
+ monitor_param['id'] = monitor_id
+ if 'name' in specs:
+ monitor_param['name'] = specs['name']
+ if 'json_query_method' in specs:
+ monitor_param['json_query_method'] = specs['json_query_method'].upper()
+ if 'description' in specs:
+ monitor_param['description'] = specs['description']
+ if 'url_path' in specs:
+ monitor_param['http-endpoint-ref'] = specs['url_path']
+ if 'ui_data' in specs:
+ if 'widget_type' in specs['ui_data']:
+ monitor_param['widget-type'] = specs['ui_data']['widget_type'].upper()
+ if 'units' in specs['ui_data']:
+ monitor_param['units'] = specs['ui_data']['units']
+ if 'group_tag' in specs['ui_data']:
+ monitor_param['group_tag'] = specs['ui_data']['group_tag']
+ if 'constraints' in specs:
+ if 'value_type' in specs['constraints']:
+ monitor_param['value-type'] = ToscaCompute.VALUE_TYPE_CONVERSION_MAP[specs['constraints']['value_type']]
+
+ return monitor_param
+
def get_vm_flavor(specs):
vm_flavor = {}
if 'num_cpus' in specs:
@@ -125,14 +177,133 @@
return vm_flavor
+ def get_host_epa(specs):
+ host_epa = {}
+ if 'cpu_model' in specs:
+ host_epa["cpu-model"] = specs['cpu_model'].upper()
+ if 'cpu_arch' in specs:
+ host_epa["cpu-arch"] = specs['cpu_arch'].upper()
+ if 'cpu_vendor' in specs:
+ host_epa["cpu-vendor"] = specs['cpu_vendor'].upper()
+ if 'cpu_socket_count' in specs:
+ host_epa["cpu-socket-count"] = specs['cpu_socket_count']
+ if 'cpu_core_count' in specs:
+ host_epa["cpu-core-count"] = specs['cpu_core_count']
+ if 'cpu_core_thread_count' in specs:
+ host_epa["cpu-core-thread-count"] = specs['cpu_core_thread_count']
+ if 'om_cpu_model_string' in specs:
+ host_epa["om-cpu-model-string"] = specs['om_cpu_model_string']
+ if 'cpu_feature' in specs:
+ cpu_feature_prop = []
+ for spec in specs['cpu_feature']:
+ cpu_feature_prop.append({'feature':spec.upper()})
+ host_epa['cpu-feature'] = cpu_feature_prop
+ if 'om_cpu_feature' in specs:
+ cpu_feature_prop = []
+ for spec in specs['om_cpu_feature']:
+ cpu_feature_prop.append({'feature':spec})
+ host_epa['om-cpu-feature'] = cpu_feature_prop
+ return host_epa;
+
+ def get_vswitch_epa(specs):
+ vswitch_epa = {}
+ if 'ovs_acceleration' in specs:
+ vswitch_epa['ovs-acceleration'] = specs['ovs_acceleration'].upper()
+ if 'ovs_offload' in specs:
+ vswitch_epa['ovs-offload'] = specs['ovs_offload'].upper()
+ return vswitch_epa
+
+ def get_hypervisor_epa(specs):
+ hypervisor_epa = {}
+ if 'type' in specs:
+ hypervisor_epa['type'] = specs['type'].upper()
+ if 'version' in specs:
+ hypervisor_epa['version'] = str(specs['version'])
+
+ return hypervisor_epa
+
+ def get_guest_epa(specs, nfv_comput_specs):
+ guest_epa = {}
+ guest_epa['numa-node-policy'] = {}
+ guest_epa['numa-node-policy']['node'] = []
+ if 'mem_policy' in specs:
+ guest_epa['numa-node-policy']['mem-policy'] = specs['mem_policy'].upper()
+ if 'node_cnt' in specs:
+ guest_epa['numa-node-policy']['node-cnt'] = specs['node_cnt']
+ if 'node' in specs:
+ for node in specs['node']:
+ node_prop = {}
+ if 'id' in node:
+ node_prop['id'] = node['id']
+ if 'mem_size' in node:
+ if 'MiB' in node['mem_size'] or 'MB' in node['mem_size']:
+ node_prop['memory-mb'] = int(node['mem_size'].replace('MB',''))
+ else:
+ err_msg = "Specify mem_size of NUMA extension should be in MB"
+ raise ValidationError(message=err_msg)
+ if 'vcpus' in node:
+ vcpu_lis =[]
+ for vcpu in node['vcpus']:
+ vcpu_lis.append({'id': vcpu})
+ node_prop['vcpu'] = vcpu_lis
+ if 'om_numa_type' in node:
+ numa_type = node['om_numa_type']
+ if 'paired-threads' == numa_type:
+ node_prop['paired_threads'] = {}
+ node_prop['paired_threads']['num_paired_threads'] = node['paired_threads']['num_paired_threads']
+ elif 'threads' == numa_type:
+ if 'num_threads' in node:
+ node_prop['num_threads'] = node['num_threads']
+ elif 'cores' == numa_type:
+ if 'num_cores' in node:
+ node_prop['num_cores'] = node['num_cores']
+ else:
+ err_msg = "om_numa_type should be among cores, paired-threads or threads"
+ raise ValidationError(message=err_msg)
+ guest_epa['numa-node-policy']['node'].append(node_prop)
+
+ if 'mem_page_size' in nfv_comput_specs:
+ guest_epa['mempage-size'] = self.TOSCA_MEM_SIZE[nfv_comput_specs['mem_page_size']]
+ if 'cpu_allocation' in nfv_comput_specs:
+ if 'cpu_affinity' in nfv_comput_specs['cpu_allocation']:
+ guest_epa['cpu-pinning-policy'] = nfv_comput_specs['cpu_allocation']['cpu_affinity'].upper()
+ guest_epa['trusted-execution'] = False
+ if 'thread_allocation' in nfv_comput_specs['cpu_allocation']:
+ guest_epa['cpu-thread-pinning-policy'] = nfv_comput_specs['cpu_allocation']['thread_allocation'].upper()
+
+ return guest_epa
+
tosca_caps = self.get_tosca_caps()
self.log.debug(_("VDU {0} tosca capabilites: {1}").
format(self.name, tosca_caps))
-
- if 'host' in tosca_caps:
- self.properties['vm-flavor'] = get_vm_flavor(tosca_caps['host'])
+ if 'nfv_compute' in tosca_caps:
+ self.properties['vm-flavor'] = get_vm_flavor(tosca_caps['nfv_compute'])
self.log.debug(_("VDU {0} properties: {1}").
format(self.name, self.properties))
+ if 'host_epa' in tosca_caps:
+ self.properties['host-epa'] = get_host_epa(tosca_caps['host_epa'])
+ if 'hypervisor_epa' in tosca_caps:
+ self.properties['hypervisor-epa'] = get_hypervisor_epa(tosca_caps['hypervisor_epa'])
+ if 'vswitch_epa' in tosca_caps:
+ self.properties['vswitch-epa'] = get_vswitch_epa(tosca_caps['vswitch_epa'])
+ if 'numa_extension' in tosca_caps:
+ self.properties['guest-epa'] = get_guest_epa(tosca_caps['numa_extension'], tosca_caps['nfv_compute'])
+ if 'monitoring_param' in tosca_caps:
+ self._monitor_param.append(get_monitor_param(tosca_caps['monitoring_param'], '1'))
+ if 'monitoring_param_1' in tosca_caps:
+ self._monitor_param.append(get_monitor_param(tosca_caps['monitoring_param_1'], '2'))
+ if 'mgmt_interface' in tosca_caps:
+ self._mgmt_interface = get_mgmt_interface(tosca_caps['mgmt_interface'])
+ if len(self._mgmt_interface) > 0:
+ prop = {}
+ if 'dashboard-params' in self._mgmt_interface:
+ if 'path' in self._mgmt_interface['dashboard-params']:
+ prop['path'] = self._mgmt_interface['dashboard-params']['path']
+ if 'port' in self._mgmt_interface['dashboard-params']:
+ prop['port'] = self._mgmt_interface['dashboard-params']['port']
+ self._http_endpoint = prop
+
+
def handle_artifacts(self):
if self.artifacts is None:
@@ -145,20 +316,20 @@
if isinstance(props, dict):
details = {}
for name, value in props.items():
- if name == 'type':
+ if name == 'type' and value == 'tosca.artifacts.Deployment.Image.riftio.QCOW2':
prefix, type_ = value.rsplit('.', 1)
if type_ == 'QCOW2':
details['type'] = 'qcow2'
- else:
- err_msg = _("VDU {0}, Currently only QCOW2 images "
- "are supported in artifacts ({1}:{2})"). \
- format(self.name, key, value)
- self.log.error(err_msg)
- raise ValidationError(message=err_msg)
+ self._image = props['file']
+ self.properties['image'] = os.path.basename(props['file'])
+ elif name == 'type' and value == 'tosca.artifacts.Deployment.riftio.cloud_init_file':
+ details['cloud_init_file'] = os.path.basename(props['file'])
+ self._cloud_init = props['file']
+ self.properties['cloud_init_file'] = os.path.basename(props['file'])
elif name == 'file':
details['file'] = value
elif name == 'image_checksum':
- details['image_checksum'] = value
+ self.properties['image_checksum'] = value
else:
self.log.warn(_("VDU {0}, unsuported attribute {1}").
format(self.name, name))
@@ -192,6 +363,7 @@
return None
def update_image_checksum(self, in_file):
+
# Create image checksum
# in_file is the TOSCA yaml file location
if self._image is None:
@@ -249,7 +421,15 @@
return None
self._update_properties_for_model()
props = convert_keys_to_python(self.properties)
+
+ for monitor_param in self._monitor_param:
+ monitor_props = convert_keys_to_python(monitor_param)
+ vnfd.monitoring_param.add().from_dict(monitor_props)
try:
+ if len(self._mgmt_interface) > 0:
+ vnfd.mgmt_interface.from_dict(convert_keys_to_python(self._mgmt_interface))
+ if self._http_endpoint:
+ vnfd.http_endpoint.add().from_dict(convert_keys_to_python(self._http_endpoint))
vnfd.vdu.add().from_dict(props)
except Exception as e:
err_msg = _("{0} Exception vdu from dict {1}: {2}"). \
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py
new file mode 100644
index 0000000..7b8657d
--- /dev/null
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_graph.py
@@ -0,0 +1,62 @@
+from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+from toscaparser.functions import GetInput
+
+TARGET_CLASS_NAME = 'ToscaForwardingGraph'
+class ToscaForwardingGraph(ManoResource):
+ '''Translate TOSCA node type tosca.nodes.nfv.FP'''
+ toscatype = 'tosca.groups.nfv.VNFFG'
+
+ def __init__(self, log, group, metadata=None):
+ #super(ToscaForwardingGraph, self).__init__(log, nodetemplate, type_='forwardgraph', metadata=metadata)
+ super(ToscaForwardingGraph, self).__init__(log,
+ group,
+ type_="vnfgd",
+ metadata=metadata)
+ self.name = group.name
+ self.type_ = 'vnfgd'
+ self.metadata = metadata
+ self.group = group
+ self.properties = {}
+ self.classifiers = []
+ self.rsp = []
+ self.log = log
+
+ def get_tosca_group_props(self):
+ tosca_props = {}
+ for prop in self.group.get_properties_objects():
+ if isinstance(prop.value, GetInput):
+ tosca_props[prop.name] = {'get_param': prop.value.input_name}
+ else:
+ tosca_props[prop.name] = prop.value
+ return tosca_props
+
+ def handle_properties(self, nodes, groups):
+ self.properties['name'] = self.name
+ self.properties['vendor'] = self.metadata['vendor']
+ self.properties['id'] = self.id
+ self.properties['classifier'] = []
+ self.properties['rsp'] = []
+
+ tosca_props = self.get_tosca_group_props()
+ forwarding_paths = []
+ for member in self.group.members:
+ forwarding_paths.append(member)
+
+ for forwarding_path in forwarding_paths:
+ node = self.get_node_with_name(forwarding_path, nodes)
+ if node.classifier is not None:
+ self.properties['classifier'].append(node.classifier)
+ if node.rsp is not None:
+ self.properties['rsp'].append(node.rsp)
+
+ def generate_yang_model_gi(self, nsd, vnfds):
+ try:
+ nsd.vnffgd.add().from_dict(self.properties)
+ except Exception as e:
+ err_msg = "Error updating VNNFG to nsd"
+ self.log.error(err_msg)
+ raise e
+
+ def generate_yang_model(self, nsd, vnfds, use_gi=False):
+ if use_gi:
+ return self.generate_yang_model_gi(nsd, vnfds)
\ No newline at end of file
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py
new file mode 100644
index 0000000..12b7062
--- /dev/null
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_forwarding_path.py
@@ -0,0 +1,91 @@
+from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+import uuid
+
+
+TARGET_CLASS_NAME = 'ToscaForwardingPath'
+class ToscaForwardingPath(ManoResource):
+ '''Translate TOSCA node type tosca.nodes.nfv.FP'''
+
+ toscatype = 'tosca.nodes.nfv.FP'
+
+
+ def __init__(self, log, node, metadata=None):
+ super(ToscaForwardingPath, self).__init__(log, node, type_='forwarding_path', metadata=metadata)
+ self.metadata = metadata
+ self.classifier = None
+ self.rsp = None
+ self.cp = None
+ self.properties = {}
+
+ def handle_forwarding_path_dependencies(self, nodes, vnf_type_to_capability_substitution_mapping):
+
+ def get_classifier(specs):
+ classifier_prop = {}
+ classifier_prop['name'] = 'VNFFG -' + str(self.name)
+ classifier_prop['id'] = self.id
+ if 'policy' in specs:
+ classifier_prop['match_attributes'] = []
+ policy = specs['policy']
+ if 'criteria' in policy:
+ match_prop = {}
+ match_prop['id'] = str(uuid.uuid1())
+ for criteria in policy['criteria']:
+ if 'ip_dst_prefix' in criteria:
+ match_prop['destination_ip_address'] = criteria['ip_dst_prefix']
+ if 'ip_proto' in criteria:
+ match_prop['ip_proto'] = criteria['ip_proto']
+ if 'source_port_range' in criteria:
+ match_prop['source_port'] = int(criteria['source_port_range'])
+ if 'destination_port_range' in criteria:
+ match_prop['destination_port'] = int(criteria['destination_port_range'])
+ classifier_prop['match_attributes'].append(match_prop)
+ if 'cp' in specs:
+ cp_node_name = specs['cp']['capability']
+ cp_node = self.get_node_with_name(cp_node_name, nodes)
+ if cp_node:
+ classifier_prop['vnfd_connection_point_ref'] = cp_node.cp_name
+ if 'cp' in specs:
+ vnf_node_name = specs['cp']['forwarder']
+ vnf_node = self.get_node_with_name(vnf_node_name, nodes)
+ if vnf_node:
+ classifier_prop['vnfd_id_ref'] = vnf_node.id
+ classifier_prop['member_vnf_index_ref'] = vnf_node.get_member_vnf_index()
+ return classifier_prop
+
+ def get_rsp(specs):
+ rsp = {}
+ rsp['id'] = str(uuid.uuid1())
+ rsp['name'] = 'VNFFG-RSP-' + str(self.name)
+ rsp['vnfd_connection_point_ref'] = []
+ if 'path' in specs:
+ fp_connection_point = []
+ vnf_index = 1
+ order_index = 1
+ visited_cps = []
+ for rsp_item in specs['path']:
+ vnf_node_name = rsp_item['forwarder']
+ conn_forwarder = rsp_item['capability']
+ vnf_node = self.get_node_with_name(vnf_node_name, nodes)
+
+ for subs_mapping in vnf_type_to_capability_substitution_mapping[vnf_node.vnf_type]:
+ prop = {}
+ if conn_forwarder in subs_mapping:
+ fp_connection_point.append(subs_mapping[conn_forwarder])
+ cp_node_name = subs_mapping[conn_forwarder]
+ cp_node = self.get_node_with_name(cp_node_name, nodes)
+ if cp_node.cp_name not in visited_cps:
+ prop['vnfd_connection_point_ref'] = cp_node.cp_name
+ prop['vnfd_id_ref'] = vnf_node.id
+ prop['member_vnf_index_ref'] = vnf_node.get_member_vnf_index()
+ prop['order'] = order_index
+ rsp['vnfd_connection_point_ref'].append(prop)
+ vnf_index = vnf_index + 1
+ order_index = order_index + 1
+ visited_cps.append(cp_node.cp_name)
+ return rsp
+
+ tosca_props = self.get_tosca_props()
+ self.classifier = get_classifier(tosca_props)
+ self.rsp = get_rsp(tosca_props)
+ if self.classifier and self.rsp:
+ self.classifier['rsp_id_ref'] = self.rsp['id']
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py
index 7c03d56..9b7cd03 100644
--- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_initial_config.py
@@ -18,6 +18,7 @@
from rift.mano.tosca_translator.common.utils import _
from rift.mano.tosca_translator.common.utils import convert_keys_to_python
from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+from toscaparser.functions import GetInput
from toscaparser.common.exception import ValidationError
@@ -29,18 +30,16 @@
class ToscaInitialConfig(ManoResource):
'''Translate TOSCA node type tosca.policies.InitialConfigPrimitive.'''
- toscatype = 'tosca.policies.riftio.InitialConfigPrimitive'
+ toscatype = 'tosca.policies.nfv.riftio.initial_config_primitive'
IGNORE_PROPS = []
- def __init__(self, log, primitive, metadata=None):
+ def __init__(self, log, policy, metadata=None):
# TODO(Philip):Not inheriting for ManoResource, as there is no
# instance from parser
self.log = log
- for name, details in primitive.items():
- self.name = name
- self.details = details
- break
+ self.name = policy.name
+ self.policy = policy
self.type_ = 'initial-cfg'
self.metadata = metadata
self.properties = {}
@@ -50,7 +49,7 @@
return "%s(%s)" % (self.name, self.type)
def handle_properties(self, nodes, groups):
- tosca_props = self.details
+ tosca_props = self.get_policy_props()
self.log.debug(_("{0} with tosca properties: {1}").
format(self, tosca_props))
self.properties['name'] = tosca_props['name']
@@ -71,6 +70,14 @@
self.log.debug(_("{0} properties: {1}").format(self, self.properties))
+ def get_policy_props(self):
+ tosca_props = {}
+ for prop in self.policy.get_properties_objects():
+ if isinstance(prop.value, GetInput):
+ tosca_props[prop.name] = {'get_param': prop.value.input_name}
+ else:
+ tosca_props[prop.name] = prop.value
+ return tosca_props
def get_yang_model_gi(self, nsd, vnfds):
props = convert_keys_to_python(self.properties)
try:
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py
index b446e51..a9f9c77 100644
--- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py
@@ -39,48 +39,64 @@
nodetemplate,
type_='vld',
metadata=metadata)
+ self._vld = {}
+ self._ip_profile = {}
- def handle_properties(self):
+ def handle_vld_properties(self, nodes, vnf_type_substitution_mapping):
+ def get_vld_props(specs):
+ vld_prop = {}
+ vld_prop['id'] = self.id
+ vld_prop['name'] = self.name
+ vld_prop['short-name'] = self.name
+ vld_prop['type'] = self.get_type()
+ vld_prop['ip_profile_ref'] = "{0}_{1}".format(self.nodetemplate.name, "ip")
+ if 'description' in specs:
+ vld_prop['description'] = specs['description']
+ if 'vendor' in specs:
+ vld_prop['vendor'] = specs['vendor']
+
+ index_count = 1
+ vld_connection_point_list = []
+ for node in nodes:
+ if node.type == "vnfd":
+ substitution_mapping_list = vnf_type_substitution_mapping[node.vnf_type];
+ for req_key, req_value in node._reqs.items():
+ for mapping in substitution_mapping_list:
+ if req_key in mapping:
+ # link the VLD to the connection point
+ node_vld = self.get_node_with_name(mapping[req_key][0], nodes)
+ if node:
+ #print()
+ prop = {}
+ prop['member-vnf-index-ref'] = node.get_member_vnf_index()
+ prop['vnfd-connection-point-ref'] = node_vld.cp_name
+ prop['vnfd-id-ref'] = node_vld.vnf._id
+ vld_connection_point_list.append(prop)
+ index_count += 1
+ if len(vld_connection_point_list) > 1:
+ vld_prop['vnfd-connection-point-ref'] = vld_connection_point_list
+ return vld_prop
+
+ def get_ip_profile_props(specs):
+ ip_profile_prop = {}
+ ip_profile_param = {}
+ if 'ip_profile_ref' in self._vld:
+ ip_profile_prop['name'] = self._vld['ip_profile_ref']
+
+ if 'description' in specs:
+ ip_profile_prop['description'] = specs['description']
+ if 'gateway_ip' in specs:
+ ip_profile_param['gateway-address'] = specs['gateway_ip']
+ if 'ip_version' in specs:
+ ip_profile_param['ip-version'] = 'ipv' + str(specs['ip_version'])
+ if 'cidr' in specs:
+ ip_profile_param['subnet-address'] = specs['cidr']
+
+ ip_profile_prop['ip-profile-params'] = ip_profile_param
+ return ip_profile_prop
tosca_props = self.get_tosca_props()
-
- if 'cidr' in tosca_props.keys():
- self.log.warn(_("Support for subnet not yet "
- "available. Ignoring it"))
- net_props = {}
- for key, value in tosca_props.items():
- if key in self.NETWORK_PROPS:
- if key == 'network_name':
- net_props['name'] = value
- elif key == 'network_id':
- net_props['id'] = value
- else:
- net_props[key] = value
-
- net_props['type'] = self.get_type()
-
- if 'name' not in net_props:
- # Use the node name as network name
- net_props['name'] = self.name
-
- if 'short_name' not in net_props:
- # Use the node name as network name
- net_props['short-name'] = self.name
-
- if 'id' not in net_props:
- net_props['id'] = self.id
-
- if 'description' not in net_props:
- net_props['description'] = self.description
-
- if 'vendor' not in net_props:
- net_props['vendor'] = self.vendor
-
- if 'version' not in net_props:
- net_props['version'] = self.version
-
- self.log.debug(_("Network {0} properties: {1}").
- format(self.name, net_props))
- self.properties = net_props
+ self._vld = get_vld_props(tosca_props)
+ self._ip_profile = get_ip_profile_props(tosca_props)
def get_type(self):
"""Get the network type based on propery or type derived from"""
@@ -107,9 +123,12 @@
return "ELAN"
def generate_yang_model_gi(self, nsd, vnfds):
- props = convert_keys_to_python(self.properties)
+ props = convert_keys_to_python(self.properties)
+ vld_props = convert_keys_to_python(self._vld)
+ ip_profile_props = convert_keys_to_python(self._ip_profile)
try:
- nsd.vld.add().from_dict(props)
+ nsd.vld.add().from_dict(vld_props)
+ nsd.ip_profiles.add().from_dict(ip_profile_props)
except Exception as e:
err_msg = _("{0} Exception vld from dict {1}: {2}"). \
format(self, props, e)
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py
index 04e3a59..3574355 100644
--- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_port.py
@@ -40,6 +40,8 @@
metadata=metadata)
# Default order
self.order = 0
+ self.vnf = None
+ self.cp_name = None
pass
def handle_properties(self):
@@ -68,28 +70,32 @@
self.log.warn(err_msg)
raise ValidationError(message=err_msg)
+ self.cp_name = port_props['name']
self.properties = port_props
def handle_requirements(self, nodes):
tosca_reqs = self.get_tosca_reqs()
+ tosca_caps = self.get_tosca_caps()
self.log.debug("VNF {0} requirements: {1}".
format(self.name, tosca_reqs))
vnf = None # Need vnf ref to generate cp refs in vld
vld = None
+ '''
if len(tosca_reqs) != 2:
err_msg = _("Invalid configuration as incorrect number of "
"requirements for CP {0} are specified"). \
format(self)
self.log.error(err_msg)
raise ValidationError(message=err_msg)
-
+ '''
for req in tosca_reqs:
if 'virtualBinding' in req:
target = req['virtualBinding']['target']
node = self.get_node_with_name(target, nodes)
if node:
vnf = node.vnf
+ self.vnf = node._vnf
if not vnf:
err_msg = _("No vnfs linked to a VDU {0}"). \
format(node)
@@ -129,17 +135,20 @@
self.log.error(err_msg)
raise ValidationError(message=err_msg)
- if vnf and vld:
+ if 'sfc' in tosca_caps and vnf:
+ if 'sfc_type' in tosca_caps['sfc']:
+ vnf.properties['service-function-chain'] = tosca_caps['sfc']['sfc_type'].upper()
+ if 'sf_type' in tosca_caps['sfc']:
+ vnf.properties['service-function-type'] = tosca_caps['sfc']['sf_type']
+
+ if vnf:
cp_ref = {}
cp_ref['vnfd-connection-point-ref'] = self.properties['name']
cp_ref['vnfd-id-ref'] = vnf.properties['id']
cp_ref['member-vnf-index-ref'] = \
vnf._const_vnfd['member-vnf-index']
- if 'vnfd-connection-point-ref' not in vld.properties:
- vld.properties['vnfd-connection-point-ref'] = []
- vld.properties['vnfd-connection-point-ref'].append(cp_ref)
else:
- err_msg = _("CP {0}, VNF {1} or VL {2} not found"). \
+ err_msg = _("CP {0}, VNF {1} not found"). \
format(self, vnf, vld)
self.log.error(err_msg)
raise ValidationError(message=err_msg)
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py
index 3e52967..e4e045e 100644
--- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_nfv_vnf.py
@@ -18,6 +18,7 @@
from rift.mano.tosca_translator.common.utils import _
from rift.mano.tosca_translator.common.utils import convert_keys_to_python
from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+from toscaparser.functions import GetInput
from toscaparser.common.exception import ValidationError
@@ -45,7 +46,7 @@
'mgmt-interface']
OPTIONAL_PROPS = ['version', 'vendor', 'http-endpoint', 'monitoring-param',
'connection-point']
- IGNORE_PROPS = ['port']
+ IGNORE_PROPS = ['port', 'monitoring_param']
TOSCA_CAPS = ['mgmt_interface', 'http_endpoint', 'monitoring_param_0',
'monitoring_param_1', 'connection_point']
@@ -57,6 +58,10 @@
self._const_vnfd = {}
self._vnf_config = {}
self._vdus = []
+ self._policies = []
+ self._cps = []
+ self.vnf_type = nodetemplate.type
+ self._reqs = {}
def map_tosca_name_to_mano(self, name):
new_name = super().map_tosca_name_to_mano(name)
@@ -138,6 +143,8 @@
if 'start_by_default' in vnf_props:
self._const_vnfd['start-by-default'] = \
vnf_props.pop('start_by_default')
+ if 'logo' in self.metadata:
+ vnf_props['logo'] = self.metadata['logo']
self.log.debug(_("VNF {0} with constituent vnf: {1}").
format(self.name, self._const_vnfd))
@@ -186,45 +193,44 @@
self.log.debug(_("VDU {0} properties: {1}").
format(self.name, self.properties))
- def handle_requirements(self, nodes):
+ def handle_requirements(self, nodes, policies, vnf_type_to_vdus_map):
tosca_reqs = self.get_tosca_reqs()
- self.log.debug("VNF {0} requirements: {1}".
- format(self.name, tosca_reqs))
+ for req in tosca_reqs:
+ for key, value in req.items():
+ if 'target' in value:
+ self._reqs[key] = value['target']
- try:
- for req in tosca_reqs:
- if 'vdus' in req:
- target = req['vdus']['target']
- node = self.get_node_with_name(target, nodes)
- if node:
- self._vdus.append(node)
- node._vnf = self
- # Add the VDU id to mgmt-intf
- if 'mgmt-interface' in self.properties:
- self.properties['mgmt-interface']['vdu-id'] = \
- node.id
- if 'vdu' in self.properties['mgmt-interface']:
- # Older yang
- self.properties['mgmt-interface'].pop('vdu')
- else:
- err_msg = _("VNF {0}, VDU {1} specified not found"). \
- format(self.name, target)
- self.log.error(err_msg)
- raise ValidationError(message=err_msg)
+ for policy in policies:
+ if hasattr(policy, '_vnf_name') and policy._vnf_name == self.name:
+ self._policies.append(policy)
- except Exception as e:
- err_msg = _("Exception getting VDUs for VNF {0}: {1}"). \
- format(self.name, e)
- self.log.error(err_msg)
- raise e
- self.log.debug(_("VNF {0} properties: {1}").
- format(self.name, self.properties))
+ if self.vnf_type in vnf_type_to_vdus_map:
+ for vdu_node_name in vnf_type_to_vdus_map[self.vnf_type]:
+ node = self.get_node_with_name(vdu_node_name, nodes)
+ if node:
+ self._vdus.append(node)
+ node._vnf = self
+ # Add the VDU id to mgmt-intf
+ if 'mgmt-interface' in self.properties:
+ self.properties['mgmt-interface']['vdu-id'] = \
+ node.id
+ if 'vdu' in self.properties['mgmt-interface']:
+ # Older yang
+ self.properties['mgmt-interface'].pop('vdu')
+ else:
+ err_msg = _("VNF {0}, VDU {1} specified not found"). \
+ format(self.name, target)
+ self.log.error(err_msg)
+ raise ValidationError(message=err_msg)
def generate_yang_model_gi(self, nsd, vnfds):
vnfd_cat = RwVnfdYang.YangData_Vnfd_VnfdCatalog()
vnfd = vnfd_cat.vnfd.add()
props = convert_keys_to_python(self.properties)
+ for key in ToscaNfvVnf.IGNORE_PROPS:
+ if key in props:
+ props.pop(key)
try:
vnfd.from_dict(props)
except Exception as e:
@@ -237,6 +243,8 @@
# Update the VDU properties
for vdu in self._vdus:
vdu.generate_yang_submodel_gi(vnfd)
+ for policy in self._policies:
+ policy.generate_yang_submodel_gi(vnfd)
# Update constituent vnfd in nsd
try:
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py
new file mode 100644
index 0000000..8b8771b
--- /dev/null
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_placement_group.py
@@ -0,0 +1,114 @@
+#
+# Copyright 2016 RIFT.io Inc
+#
+# 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 rift.mano.tosca_translator.common.utils import _
+from rift.mano.tosca_translator.common.utils import convert_keys_to_python
+from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+from toscaparser.functions import GetInput
+from rift.mano.tosca_translator.common.utils import convert_keys_to_python
+
+from toscaparser.common.exception import ValidationError
+
+
+# Name used to dynamically load appropriate map class.
+TARGET_CLASS_NAME = 'ToscaPlacementGroup'
+
+
+class ToscaPlacementGroup(ManoResource):
+ '''Translate TOSCA node type tosca.policies.Scaling.'''
+
+ toscatype = 'tosca.policies.nfv.riftio.placement'
+
+ IGNORE_PROPS = []
+
+ def __init__(self, log, policy, metadata=None, vnf_name=None):
+ self.log = log
+ self.name = policy.name
+ self.type_ = 'place-grp'
+ self.metadata = metadata
+ self.policy = policy
+ self.properties = {}
+ self._vnf_name = vnf_name
+
+ def __str__(self):
+ return "%s(%s)" % (self.name, self.type)
+
+ def handle_properties(self, nodes, groups):
+ tosca_props = self.get_policy_props()
+ self.properties['name'] = tosca_props['name']
+ self.properties['strategy'] = tosca_props['strategy']
+ self.properties['requirement'] = tosca_props['requirement']
+ if self._vnf_name is None:
+ self.properties['member-vnfd'] = []
+ index_count = 1
+ for node in self.policy.get_targets_list():
+ vnf_node = self.get_node_with_name(node.name, nodes)
+ prop = {}
+ prop['member-vnf-index-ref'] = index_count
+ prop['vnfd-id-ref'] = vnf_node.id
+ self.properties['member-vnfd'].append(prop)
+ index_count = index_count + 1
+ else:
+ self.properties['member-vdus'] = []
+ for node in self.policy.get_targets_list():
+ vdu_node = self.get_node_with_name(node.name, nodes)
+ prop = {}
+ prop['member-vdu-ref'] = vdu_node.name
+ self.properties['member-vdus'].append(prop)
+
+ def get_yang_model_gi(self, nsd, vnfds):
+ props = convert_keys_to_python(self.properties)
+ try:
+ if self._vnf_name is None:
+ nsd.placement_groups.add().from_dict(props)
+ except Exception as e:
+ err_msg = _("{0} Exception nsd placement-groups from dict {1}: {2}"). \
+ format(self, props, e)
+ self.log.error(err_msg)
+ raise e
+
+ def generate_yang_model(self, nsd, vnfds, use_gi=False):
+ if use_gi:
+ return self.get_yang_model_gi(nsd, vnfds)
+ if 'placement-groups' not in nsd:
+ nsd['placement-groups'] = []
+
+ for key, value in self.properties.items():
+ prim[key] = value
+ nsd['placement-groups'].append(prim)
+
+ def generate_yang_submodel_gi(self, vnfd):
+ if vnfd is None:
+ return None
+ try:
+ props = convert_keys_to_python(self.properties)
+ vnfd.placement_groups.add().from_dict(props)
+ except Exception as e:
+ err_msg = _("{0} Exception policy from dict {1}: {2}"). \
+ format(self, props, e)
+ self.log.error(err_msg)
+ raise e
+
+ def get_policy_props(self):
+ tosca_props = {}
+
+ for prop in self.policy.get_properties_objects():
+ if isinstance(prop.value, GetInput):
+ tosca_props[prop.name] = {'get_param': prop.value.input_name}
+ else:
+ tosca_props[prop.name] = prop.value
+ return tosca_props
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py
index 25246af..7f427f3 100644
--- a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_scaling_group.py
@@ -18,6 +18,7 @@
from rift.mano.tosca_translator.common.utils import _
from rift.mano.tosca_translator.common.utils import convert_keys_to_python
from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+from toscaparser.functions import GetInput
from toscaparser.common.exception import ValidationError
@@ -29,54 +30,62 @@
class ToscaScalingGroup(ManoResource):
'''Translate TOSCA node type tosca.policies.Scaling.'''
- toscatype = 'tosca.policies.riftio.ScalingGroup'
+ toscatype = 'tosca.groups.nfv.riftio.scaling'
IGNORE_PROPS = []
- def __init__(self, log, policy, metadata=None):
+ def __init__(self, log, group, metadata=None):
# TODO(Philip):Not inheriting for ManoResource, as there is no
# instance from parser
self.log = log
- for name, details in policy.items():
- self.name = name
- self.details = details
- break
+ self.name = group.name
+ #self.details = details
+ self.group = group
self.type_ = 'scale-grp'
self.metadata = metadata
self.properties = {}
def __str__(self):
return "%s(%s)" % (self.name, self.type)
+ def get_tosca_group_props(self):
+ tosca_props = {}
+ for prop in self.group.get_properties_objects():
+ if isinstance(prop.value, GetInput):
+ tosca_props[prop.name] = {'get_param': prop.value.input_name}
+ else:
+ tosca_props[prop.name] = prop.value
+ return tosca_props
def handle_properties(self, nodes, groups):
- tosca_props = self.details
+ tosca_props = self.get_tosca_group_props()
self.log.debug(_("{0} with tosca properties: {1}").
format(self, tosca_props))
- self.properties['name'] = tosca_props['name']
- self.properties['max-instance-count'] = \
- tosca_props['max_instance_count']
- self.properties['min-instance-count'] = \
- tosca_props['min_instance_count']
+ if 'name ' in tosca_props:
+ self.properties['name'] = tosca_props['name']
+ if 'max_instance_count' in tosca_props:
+ self.properties['max-instance-count'] = tosca_props['max_instance_count']
+ if 'min_instance_count' in tosca_props:
+ self.properties['min-instance-count'] = tosca_props['min_instance_count']
self.properties['vnfd-member'] = []
def _get_node(name):
for node in nodes:
if node.name == name:
return node
-
- for member, count in tosca_props['vnfd_members'].items():
- node = _get_node(member)
- if node:
- memb = {}
- memb['member-vnf-index-ref'] = node.get_member_vnf_index()
- memb['count'] = count
- self.properties['vnfd-member'].append(memb)
- else:
- err_msg = _("{0}: Did not find the member node {1} in "
- "resources list"). \
- format(self, member)
- self.log.error(err_msg)
- raise ValidationError(message=err_msg)
+ if 'vnfd_members' in tosca_props:
+ for member, count in tosca_props['vnfd_members'].items():
+ node = _get_node(member)
+ if node:
+ memb = {}
+ memb['member-vnf-index-ref'] = node.get_member_vnf_index()
+ memb['count'] = count
+ self.properties['vnfd-member'].append(memb)
+ else:
+ err_msg = _("{0}: Did not find the member node {1} in "
+ "resources list"). \
+ format(self, member)
+ self.log.error(err_msg)
+ raise ValidationError(message=err_msg)
def _validate_action(action):
for group in groups:
@@ -85,25 +94,27 @@
return False
self.properties['scaling-config-action'] = []
- for action, value in tosca_props['config_actions'].items():
- conf = {}
- if _validate_action(value):
- conf['trigger'] = action
- conf['ns-config-primitive-name-ref'] = value
- self.properties['scaling-config-action'].append(conf)
- else:
- err_msg = _("{0}: Did not find the action {1} in "
- "config primitives"). \
- format(self, action)
- self.log.error(err_msg)
- raise ValidationError(message=err_msg)
+ if 'config_actions' in tosca_props:
+ for action, value in tosca_props['config_actions'].items():
+ conf = {}
+ if _validate_action(value):
+ conf['trigger'] = action
+ conf['ns-config-primitive-name-ref'] = value
+ self.properties['scaling-config-action'].append(conf)
+ else:
+ err_msg = _("{0}: Did not find the action {1} in "
+ "config primitives"). \
+ format(self, action)
+ self.log.error(err_msg)
+ raise ValidationError(message=err_msg)
self.log.debug(_("{0} properties: {1}").format(self, self.properties))
def get_yang_model_gi(self, nsd, vnfds):
props = convert_keys_to_python(self.properties)
try:
- nsd.scaling_group_descriptor.add().from_dict(props)
+ if len(self.properties['vnfd-member']) > 0:
+ nsd.scaling_group_descriptor.add().from_dict(props)
except Exception as e:
err_msg = _("{0} Exception nsd scaling group from dict {1}: {2}"). \
format(self, props, e)
diff --git a/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py
new file mode 100644
index 0000000..f90c187
--- /dev/null
+++ b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_vnf_configuration.py
@@ -0,0 +1,120 @@
+#
+# Copyright 2016 RIFT.io Inc
+#
+# 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 rift.mano.tosca_translator.common.utils import _
+from rift.mano.tosca_translator.common.utils import convert_keys_to_python
+from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+from toscaparser.functions import GetInput
+from rift.mano.tosca_translator.common.utils import convert_keys_to_python
+
+from toscaparser.common.exception import ValidationError
+
+
+# Name used to dynamically load appropriate map class.
+TARGET_CLASS_NAME = 'ToscaVnfConfiguration'
+
+
+class ToscaVnfConfiguration(ManoResource):
+ '''Translate TOSCA node type tosca.policies.Scaling.'''
+
+ toscatype = 'tosca.policies.nfv.riftio.vnf_configuration'
+
+ IGNORE_PROPS = []
+
+ def __init__(self, log, policy, metadata=None, vnf_name = None):
+ self.log = log
+ self.name = policy.name
+ self.type_ = 'place-grp'
+ self.metadata = metadata
+ self.policy = policy
+ self.properties = {}
+ self.linked_to_vnf = True
+ self._vnf_name = vnf_name
+ self._vnf_id = None
+ self.scripts = []
+
+ def __str__(self):
+ return "%s(%s)" % (self.name, self.type)
+
+ def handle_properties(self, nodes, groups):
+ tosca_props = self.get_policy_props()
+ if self._vnf_name:
+ vnf_node = self.get_node_with_name(self._vnf_name, nodes)
+ self._vnf_id = vnf_node.id
+ self.properties["vnf-configuration"] = {}
+ prop = {}
+ prop["config-attributes"] = {}
+ prop["script"] = {}
+ if 'config' in tosca_props:
+ if 'config_delay' in tosca_props['config']:
+ prop["config-attributes"]['config-delay'] = tosca_props['config']['config_delay']
+ if 'config_priority' in tosca_props['config']:
+ prop["config-attributes"]['config-priority'] = tosca_props['config']['config_priority']
+ if 'config_template' in tosca_props['config']:
+ prop["config-template"] = tosca_props['config']['config_template']
+ if 'config_details' in tosca_props['config']:
+ if 'script_type' in tosca_props['config']['config_details']:
+ prop["script"]["script-type"] = tosca_props['config']['config_details']['script_type']
+ if 'initial_config' in tosca_props:
+ prop['initial-config-primitive'] = []
+ #print("Weleek " + str(tosca_props['initial_config']))
+ for init_config in tosca_props['initial_config']:
+ if 'parameter' in init_config:
+ parameters = init_config.pop('parameter')
+ init_config['parameter'] = []
+ for key, value in parameters.items():
+ init_config['parameter'].append({'name': key, 'value': str(value)})
+ if 'user_defined_script' in init_config:
+ self.scripts.append('../scripts/{}'. \
+ format(init_config['user_defined_script']))
+ prop['initial-config-primitive'].append(init_config)
+
+ self.properties = prop
+
+ def generate_yang_submodel_gi(self, vnfd):
+ if vnfd is None:
+ return None
+ try:
+ props = convert_keys_to_python(self.properties)
+ vnfd.vnf_configuration.from_dict(props)
+ except Exception as e:
+ err_msg = _("{0} Exception vdu from dict {1}: {2}"). \
+ format(self, props, e)
+ self.log.error(err_msg)
+ raise e
+
+ def get_policy_props(self):
+ tosca_props = {}
+
+ for prop in self.policy.get_properties_objects():
+ if isinstance(prop.value, GetInput):
+ tosca_props[prop.name] = {'get_param': prop.value.input_name}
+ else:
+ tosca_props[prop.name] = prop.value
+ return tosca_props
+ def get_supporting_files(self, files, desc_id=None):
+ if not len(self.scripts):
+ return
+
+ if self._vnf_id not in files:
+ files[desc_id] = []
+
+ for script in self.scripts:
+ files[self._vnf_id].append({
+ 'type': 'script',
+ 'name': script,
+ },)
\ No newline at end of file
diff --git a/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py b/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py
index dbfaa62..2d6c3e1 100644
--- a/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py
+++ b/common/python/rift/mano/tosca_translator/rwmano/translate_node_templates.py
@@ -23,6 +23,7 @@
from rift.mano.tosca_translator.common.exception import ToscaModImportError
from rift.mano.tosca_translator.conf.config import ConfigProvider as translatorConfig
from rift.mano.tosca_translator.rwmano.syntax.mano_resource import ManoResource
+from toscaparser.tosca_template import ToscaTemplate
class TranslateNodeTemplates(object):
@@ -161,6 +162,8 @@
for key in FIELDS_MAP:
if key in tosca_meta.keys():
metadata[FIELDS_MAP[key]] = str(tosca_meta[key])
+ if 'logo' in tosca_meta:
+ metadata['logo'] = os.path.basename(tosca_meta['logo'])
self.log.debug(_("Metadata {0}").format(metadata))
self.metadata = metadata
@@ -188,8 +191,51 @@
self.log.debug(_('Translating the node templates.'))
# Copy the TOSCA graph: nodetemplate
+ all_node_templates = []
+ node_to_artifact_map = {}
+ vnf_type_to_vnf_node = {}
+ vnf_type_to_vdus_map = {}
+ vnf_type_substitution_mapping = {}
+ vnf_type_to_capability_substitution_mapping = {}
tpl = self.tosca.tpl['topology_template']['node_templates']
+ associated_vnfd_flag = False
+
for node in self.nodetemplates:
+ all_node_templates.append(node)
+ if node.parent_type.type == 'tosca.nodes.nfv.riftio.VNF1':
+ vnf_type_to_vnf_node[node.type] = node.name
+ for node_key in tpl:
+ if 'artifacts' in tpl[node_key]:
+ node_to_artifact_map[node_key] = tpl[node_key]['artifacts']
+ for template in self.tosca.nested_tosca_templates_with_topology:
+ tpl_node = template.tpl['node_templates']
+ vnf_type = template.substitution_mappings.node_type
+
+ vnf_type_to_vdus_map[vnf_type] = []
+ vnf_type_substitution_mapping[vnf_type] = []
+ vnf_type_to_capability_substitution_mapping[vnf_type] = []
+ vnf_type_to_capability_substitution_mapping[vnf_type] = []
+ policies = []
+
+ for node in template.nodetemplates:
+ all_node_templates.append(node)
+ for node_key in tpl_node:
+ if 'artifacts' in tpl_node[node_key]:
+ node_to_artifact_map[node_key] = tpl_node[node_key]['artifacts']
+ for node in template.nodetemplates:
+ if 'VDU' in node.type:
+ vnf_type_to_vdus_map[vnf_type].append(node.name)
+ for policy in template.policies:
+ policies.append(policy.name)
+ for req in template.substitution_mappings.requirements:
+ vnf_type_substitution_mapping[template.substitution_mappings.node_type].append(req)
+ if template.substitution_mappings.capabilities:
+ for capability in template.substitution_mappings.capabilities:
+ sub_list = template.substitution_mappings.capabilities[capability]
+ if len(sub_list) > 0:
+ vnf_type_to_capability_substitution_mapping[vnf_type].append({capability: sub_list[0]})
+
+ for node in all_node_templates:
base_type = ManoResource.get_base_type(node.type_definition)
self.log.debug(_("Translate node %(name)s of type %(type)s with "
"base %(base)s") %
@@ -203,46 +249,73 @@
metadata=self.metadata)
# Currently tosca-parser does not add the artifacts
# to the node
- if mano_node.name in tpl:
- tpl_node = tpl[mano_node.name]
- self.log.debug("Check artifacts for {}".format(tpl_node))
- if 'artifacts' in tpl_node:
- mano_node.artifacts = tpl_node['artifacts']
+ if mano_node.type == 'vnfd':
+ associated_vnfd_flag = True
+ if mano_node.name in node_to_artifact_map:
+ mano_node.artifacts = node_to_artifact_map[mano_node.name]
self.mano_resources.append(mano_node)
self.mano_lookup[node] = mano_node
+ if not associated_vnfd_flag:
+ dummy_file = "{0}{1}".format(os.getenv('RIFT_INSTALL'), "/usr/rift/mano/common/dummy_vnf_node.yaml")
+ tosca_vnf = ToscaTemplate(dummy_file, {}, True)
+ vnf_type = self.tosca.topology_template.substitution_mappings.node_type
+ vnf_type_to_vdus_map[vnf_type] = []
+
+ for node in tosca_vnf.nodetemplates:
+ all_node_templates.append(node)
+ base_type = ManoResource.get_base_type(node.type_definition)
+ vnf_type_to_vnf_node[vnf_type] = node.name
+ mano_node = TranslateNodeTemplates. \
+ TOSCA_TO_MANO_TYPE[base_type.type](
+ self.log,
+ node,
+ metadata=self.metadata)
+ mano_node.vnf_type = vnf_type
+ self.mano_resources.append(mano_node)
+ print("Adding a new node")
+
+ for node in self.tosca.nodetemplates:
+ if 'VDU' in node.type:
+ vnf_type_to_vdus_map[vnf_type].append(node.name)
+
# The parser currently do not generate the objects for groups
- if 'groups' in self.tosca.tpl['topology_template']:
- tpl = self.tosca.tpl['topology_template']['groups']
- self.log.debug("Groups: {}".format(tpl))
- for group, details in tpl.items():
- self.log.debug(_("Translate group {}: {}").
- format(group, details))
- group_type = details['type']
- if group_type:
- group_node = TranslateNodeTemplates. \
- TOSCA_TO_MANO_TYPE[group_type](
- self.log,
- group,
- details,
- metadata=self.metadata)
- self.mano_groups.append(group_node)
+ for group in self.tosca.topology_template.groups:
+ group_type = group.type
+ if group_type:
+ group_node = TranslateNodeTemplates. \
+ TOSCA_TO_MANO_TYPE[group_type](
+ self.log,
+ group,
+ metadata=self.metadata)
+ self.mano_groups.append(group_node)
# The parser currently do not generate the objects for policies
- if 'policies' in self.tosca.tpl['topology_template']:
- tpl = self.tosca.tpl['topology_template']['policies']
- # for policy in self.policies:
- for policy in tpl:
- self.log.debug(_("Translate policy {}").
- format(policy))
- policy_type = self._get_policy_type(policy)
- if policy_type:
- policy_node = TranslateNodeTemplates. \
- TOSCA_TO_MANO_TYPE[policy_type](
- self.log,
- policy,
- metadata=self.metadata)
- self.mano_policies.append(policy_node)
+
+ for policy in self.tosca.topology_template.policies:
+ policy_type = policy.type
+ if policy_type:
+ policy_node = TranslateNodeTemplates. \
+ TOSCA_TO_MANO_TYPE[policy_type](
+ self.log,
+ policy,
+ metadata=self.metadata)
+ self.mano_policies.append(policy_node)
+ for template in self.tosca.nested_tosca_templates_with_topology:
+ vnf_type = template.substitution_mappings.node_type
+ if vnf_type in vnf_type_to_vnf_node:
+ vnf_node = vnf_type_to_vnf_node[vnf_type]
+
+ for policy in template.policies:
+ policy_type = policy.type
+ if policy_type:
+ policy_node = TranslateNodeTemplates. \
+ TOSCA_TO_MANO_TYPE[policy_type](
+ self.log,
+ policy,
+ metadata=self.metadata,
+ vnf_name=vnf_node)
+ self.mano_policies.append(policy_node)
for node in self.mano_resources:
self.log.debug(_("Handle properties for {0} of type {1}").
@@ -272,7 +345,8 @@
self.log.debug(_("Handle requirements for {0} of "
"type {1}").
format(node.name, node.type_))
- node.handle_requirements(self.mano_resources)
+ node.handle_requirements(self.mano_resources, self.mano_policies, vnf_type_to_vdus_map)
+
except Exception as e:
self.log.error(_("Exception for {0} in requirements {1}").
format(node.name, node.type_))
@@ -290,11 +364,17 @@
format(node.name, node.type_))
self.log.exception(e)
+ for node in self.mano_resources:
+ if node.type == "vld":
+ node.handle_vld_properties(self.mano_resources, vnf_type_substitution_mapping)
+ elif node.type == 'forwarding_path':
+ node.handle_forwarding_path_dependencies(self.mano_resources, vnf_type_to_capability_substitution_mapping)
+
return self.mano_resources
def translate_groups(self):
for group in self.mano_groups:
- group.handle_properties(self.mano_resources)
+ group.handle_properties(self.mano_resources, self.mano_groups)
return self.mano_groups
def translate_policies(self):
diff --git a/common/python/rift/mano/tosca_translator/test/data/ping_pong_csar_tosca_new_spec.zip b/common/python/rift/mano/tosca_translator/test/data/ping_pong_csar_tosca_new_spec.zip
new file mode 100644
index 0000000..a755040
--- /dev/null
+++ b/common/python/rift/mano/tosca_translator/test/data/ping_pong_csar_tosca_new_spec.zip
Binary files differ
diff --git a/common/python/rift/mano/yang_translator/riftiotypes.yaml b/common/python/rift/mano/yang_translator/riftiotypes.yaml
new file mode 100644
index 0000000..18a0728
--- /dev/null
+++ b/common/python/rift/mano/yang_translator/riftiotypes.yaml
@@ -0,0 +1,1493 @@
+tosca_definitions_version: tosca_simple_profile_for_nfv_1_0
+description: Extended types
+
+
+data_types:
+ tosca.datatypes.nfv.riftio.dashboard_params:
+ properties:
+ path:
+ type: string
+ description: >-
+ The HTTP path for the dashboard
+ port:
+ type: tosca.datatypes.network.PortDef
+ description: >-
+ The HTTP port for the dashboard
+ default: 80
+ https:
+ type: boolean
+ description: >-
+ Pick HTTPS instead of HTTP , Default is false
+ default: false
+ required: false
+ tosca.datatypes.nfv.riftio.monitoring_param_ui:
+ properties:
+ description:
+ type: string
+ required: false
+ group_tag:
+ type: string
+ description: >-
+ A simple tag to group monitoring parameters
+ required: false
+ widget_type:
+ type: string
+ description: >-
+ Type of the widget
+ default: counter
+ constraints:
+ - valid_values:
+ - histogram
+ - bar
+ - gauge
+ - slider
+ - counter
+ - textbox
+ units:
+ type: string
+ required: false
+ tosca.datatypes.nfv.riftio.monitoring_param_value:
+ properties:
+ value_type:
+ type: string
+ default: integer
+ constraints:
+ - valid_values:
+ - integer
+ - float
+ - string
+ numeric_min:
+ type: integer
+ description: >-
+ Minimum value for the parameter
+ required: false
+ numeric_max:
+ type: integer
+ description: >-
+ Maxium value for the parameter
+ required: false
+ string_min:
+ type: integer
+ description: >-
+ Minimum string length for the parameter
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ string_max:
+ type: integer
+ description: >-
+ Maximum string length for the parameter
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ tosca.datatypes.compute.Container.Architecture.CPUAllocation:
+ derived_from: tosca.datatypes.Root
+ properties:
+ cpu_affinity:
+ type: string
+ required: false
+ constraints:
+ - valid_values: [shared, dedicated, any]
+ thread_allocation:
+ type: string
+ required: false
+ constraints:
+ - valid_values: [avoid, separate, isolate, prefer]
+ socket_count:
+ type: integer
+ required: false
+ core_count:
+ type: integer
+ required: false
+ thread_count:
+ type: integer
+ required: false
+
+ tosca.datatypes.compute.Container.Architecture.NUMA:
+ derived_from: tosca.datatypes.Root
+ properties:
+ id:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ vcpus:
+ type: list
+ entry_schema:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ mem_size:
+ type: scalar-unit.size
+ constraints:
+ - greater_or_equal: 0 MB
+ tosca.datatypes.nfv.riftio.paired_thread_map:
+ properties:
+ thread_a:
+ type: integer
+ required: true
+ constraints:
+ - greater_or_equal: 0
+ thread_b:
+ type: integer
+ required: true
+ constraints:
+ - greater_or_equal: 0
+
+ tosca.datatypes.nfv.riftio.paired_threads:
+ properties:
+ num_paired_threads:
+ type: integer
+ constraints:
+ - greater_or_equal: 1
+ paired_thread_ids:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.nfv.riftio.paired_thread_map
+ constraints:
+ - max_length: 16
+ required: false
+
+ tosca.datatypes.compute.riftio.numa:
+ properties:
+ id:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ vcpus:
+ type: list
+ entry_schema:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ mem_size:
+ type: scalar-unit.size
+ constraints:
+ - greater_or_equal: 0 MB
+ required: false
+ om_numa_type:
+ type: string
+ description: Openmano Numa type selection
+ constraints:
+ - valid_values: [cores, paired-threads, threads]
+ required: false
+ num_cores:
+ type: integer
+ description: Use when om_numa_type is cores
+ constraints:
+ - greater_or_equal: 1
+ required: false
+ paired_threads:
+ type: tosca.datatypes.nfv.riftio.paired_threads
+ description: Use when om_numa_type is paired-threads
+ required: false
+ num_threads:
+ type: integer
+ description: Use when om_numa_type is threads
+ constraints:
+ - greater_or_equal: 1
+ required: false
+
+ tosca.nfv.datatypes.pathType:
+ properties:
+ forwarder:
+ type: string
+ required: true
+ capability:
+ type: string
+ required: true
+
+ tosca.nfv.datatypes.aclType:
+ properties:
+ eth_type:
+ type: string
+ required: false
+ eth_src:
+ type: string
+ required: false
+ eth_dst:
+ type: string
+ required: false
+ vlan_id:
+ type: integer
+ constraints:
+ - in_range: [ 1, 4094 ]
+ required: false
+ vlan_pcp:
+ type: integer
+ constraints:
+ - in_range: [ 0, 7 ]
+ required: false
+ mpls_label:
+ type: integer
+ constraints:
+ - in_range: [ 16, 1048575]
+ required: false
+ mpls_tc:
+ type: integer
+ constraints:
+ - in_range: [ 0, 7 ]
+ required: false
+ ip_dscp:
+ type: integer
+ constraints:
+ - in_range: [ 0, 63 ]
+ required: false
+ ip_ecn:
+ type: integer
+ constraints:
+ - in_range: [ 0, 3 ]
+ required: false
+ ip_src_prefix:
+ type: string
+ required: false
+ ip_dst_prefix:
+ type: string
+ required: false
+ ip_proto:
+ type: integer
+ constraints:
+ - in_range: [ 1, 254 ]
+ required: false
+ destination_port_range:
+ type: integer
+ required: false
+ source_port_range:
+ type: integer
+ required: false
+ network_src_port_id:
+ type: string
+ required: false
+ network_dst_port_id:
+ type: string
+ required: false
+ network_id:
+ type: string
+ required: false
+ network_name:
+ type: string
+ required: false
+ tenant_id:
+ type: string
+ required: false
+ icmpv4_type:
+ type: integer
+ constraints:
+ - in_range: [ 0, 254 ]
+ required: false
+ icmpv4_code:
+ type: integer
+ constraints:
+ - in_range: [ 0, 15 ]
+ required: false
+ arp_op:
+ type: integer
+ constraints:
+ - in_range: [ 1, 25 ]
+ required: false
+ arp_spa:
+ type: string
+ required: false
+ arp_tpa:
+ type: string
+ required: false
+ arp_sha:
+ type: string
+ required: false
+ arp_tha:
+ type: string
+ required: false
+ ipv6_src:
+ type: string
+ required: false
+ ipv6_dst:
+ type: string
+ required: false
+ ipv6_flabel:
+ type: integer
+ constraints:
+ - in_range: [ 0, 1048575]
+ required: false
+ icmpv6_type:
+ type: integer
+ constraints:
+ - in_range: [ 0, 255]
+ required: false
+ icmpv6_code:
+ type: integer
+ constraints:
+ - in_range: [ 0, 7]
+ required: false
+ ipv6_nd_target:
+ type: string
+ required: false
+ ipv6_nd_sll:
+ type: string
+ required: false
+ ipv6_nd_tll:
+ type: string
+ required: false
+
+
+ tosca.datatypes.nfv.riftio.vnf_configuration:
+ properties:
+ config_type:
+ type: string
+ description: >-
+ Type of the configuration agent to use
+ constraints:
+ - valid_values: [script, netconf, rest, juju]
+ config_details:
+ type: map
+ description: >-
+ Specify the details for the config agent, like
+ script type, juju charm to use, etc.
+ config_template:
+ required: false
+ type: string
+ config_delay:
+ type: integer
+ constraints:
+ - greater_or_equal: 0
+ default: 0
+ required: false
+ config_priority:
+ type: integer
+ constraints:
+ - greater_than: 0
+
+ tosca.datatypes.nfv.riftio.parameter_value:
+ properties:
+ name:
+ type: string
+ description: Name of the parameter
+ value:
+ type: string
+ description: Value of the parameter
+
+ tosca.datatypes.nfv.riftio.config_primitive:
+ properties:
+ name:
+ type: string
+ seq:
+ type: integer
+ description: >-
+ Order in which to apply, when multiple ones are defined
+ default: 0
+ constraints:
+ - greater_or_equal: 0
+ parameter:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.nfv.riftio.parameter_value
+ user_defined_script:
+ type: string
+ tosca.datatypes.nfv.riftio.primitive_parameter:
+ properties:
+ data_type:
+ type: string
+ description: >-
+ Data type associated with the name
+ constraints:
+ - valid_values: [string, integer, boolean]
+ mandatory:
+ type: boolean
+ description: >-
+ If this field is mandatory
+ default: false
+ required: false
+ default_value:
+ type: string
+ description: >-
+ The default value for this field
+ required: false
+ parameter_pool:
+ type: string
+ description: >-
+ Parameter pool name to use for this parameter
+ required: false
+ read_only:
+ type: boolean
+ description: >-
+ The value should be greyed out by the UI.
+ Only applies to parameters with default values.
+ required: false
+ default: false
+ hidden:
+ type: boolean
+ description: >-
+ The field should be hidden by the UI.
+ Only applies to parameters with default values.
+ required: false
+ default: false
+ tosca.datatypes.nfv.riftio.primitive_parameter_group:
+ properties:
+ name:
+ type: string
+ description: >-
+ Name of the parameter group
+ mandatory:
+ type: boolean
+ description: >-
+ If this group is mandatory
+ default: false
+ required: false
+ parameter:
+ type: map
+ description: >-
+ List of parameters for the service primitive
+ entry_schema: osca.datatypes.riftio.primitive_parameter
+
+ tosca.datatypes.nfv.riftio.vnf_primitive_group:
+ properties:
+ vnf_name:
+ type: string
+ description: >-
+ Name of the VNF in the NS
+ primitive:
+ type: map
+ entry_schema:
+ type: string
+ description: >-
+ Index and name of the primitive
+
+
+capability_types:
+ tosca.capabilities.nfv.riftio.mgmt_interface:
+ derived_from: tosca.capabilities.Endpoint
+ properties:
+ static_ip:
+ type: string
+ required: false
+ description: >-
+ Specifies the static IP address for managing the VNF
+ connection_point:
+ type: string
+ required: false
+ description: >-
+ Use the ip address associated with this connection point
+ dashboard_params:
+ type: tosca.datatypes.nfv.riftio.dashboard_params
+ required: false
+ description: >-
+ Parameters for the VNF dashboard
+ tosca.capabilities.nfv.riftio.monitoring_param:
+ derived_from: tosca.capabilities.nfv.Metric
+ properties:
+ name:
+ type: string
+ required: false
+ description:
+ type: string
+ required: false
+ protocol:
+ type: string
+ default: http
+ constraints:
+ - equal: http
+ polling_interval:
+ type: scalar-unit.time
+ description: >-
+ The HTTP polling interval in seconds
+ default: 2 s
+ username:
+ type: string
+ description: >-
+ The HTTP basic auth username
+ required: false
+ password:
+ type: string
+ description: >-
+ The HTTP basic auth password
+ required: false
+ method:
+ type: string
+ description: >-
+ This is the method to be performed at the uri.
+ GET by default for action
+ default: get
+ constraints:
+ - valid_values: [post, put, get, delete, options, patch]
+ headers:
+ type: map
+ entry_schema:
+ type: string
+ description: >-
+ Custom HTTP headers to put on HTTP request
+ required: false
+ json_query_method:
+ type: string
+ description: >-
+ The method to extract a value from a JSON response
+ namekey - Use the name as the key for a non-nested value.
+ jsonpath - Use jsonpath-rw implemenation to extract a value.
+ objectpath - Use objectpath implemenation to extract a value.
+ constraints:
+ - valid_values: [namekey, jsonpath, objectpath]
+ default: namekey
+ json_query_path:
+ type: string
+ description: >-
+ The json path to use to extract value from JSON structure
+ required: false
+ json_object_path:
+ type: string
+ description: >-
+ The object path to use to extract value from JSON structure
+ required: false
+ ui_data:
+ type: tosca.datatypes.nfv.riftio.monitoring_param_ui
+ required: false
+ constraints:
+ type: tosca.datatypes.nfv.riftio.monitoring_param_value
+ required: false
+ tosca.capabilities.nfv.riftio.numa_extension:
+ derived_from: tosca.capabilities.Root
+ properties:
+ node_cnt:
+ type: integer
+ description: >-
+ The number of numa nodes to expose to the VM
+ constraints:
+ - greater_or_equal: 0
+ mem_policy:
+ type: string
+ description: >-
+ This policy specifies how the memory should
+ be allocated in a multi-node scenario.
+ STRICT - The memory must be allocated
+ strictly from the memory attached
+ to the NUMA node.
+ PREFERRED - The memory should be allocated
+ preferentially from the memory
+ attached to the NUMA node
+ constraints:
+ - valid_values: [strict, preferred, STRICT, PREFERRED]
+ node:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.compute.riftio.numa
+ tosca.capabilities.nfv.riftio.vswitch_epa:
+ derived_from: tosca.capabilities.Root
+ properties:
+ ovs_acceleration:
+ type: string
+ description: |-
+ Specifies Open vSwitch acceleration mode.
+ MANDATORY - OVS acceleration is required
+ PREFERRED - OVS acceleration is preferred
+ constraints:
+ - valid_values: [mandatory, preferred, disabled, MANDATORY, PREFERRED, DISABLED]
+ ovs_offload:
+ type: string
+ description: |-
+ Specifies Open vSwitch hardware offload mode.
+ MANDATORY - OVS offload is required
+ PREFERRED - OVS offload is preferred
+ constraints:
+ - valid_values: [mandatory, preferred, disabled, MANDATORY, PREFERRED, DISABLED]
+
+ tosca.capabilities.nfv.riftio.hypervisor_epa:
+ derived_from: tosca.capabilities.Root
+ properties:
+ type:
+ type: string
+ description: |-
+ Specifies the type of hypervisor.
+ constraints:
+ - valid_values: [prefer_kvm, require_kvm, PREFER_KVM, REQUIRE_KVM]
+ version:
+ type: string
+
+ tosca.capabilities.nfv.riftio.host_epa:
+ derived_from: tosca.capabilities.Root
+ properties:
+ cpu_model:
+ type: string
+ description: >-
+ Host CPU model. Examples include SandyBridge,
+ IvyBridge, etc.
+ required: false
+ constraints:
+ - valid_values:
+ - prefer_westmere
+ - require_westmere
+ - prefer_sandbridge
+ - require_sandybridge
+ - prefer_ivybridge
+ - require_ivybridge
+ - prefer_haswell
+ - require_haswell
+ - prefer_broadwell
+ - require_broadwell
+ - prefer_nehalem
+ - require_nehalem
+ - prefer_penryn
+ - require_penryn
+ - prefer_conroe
+ - require_conroe
+ - prefer_core2duo
+ - require_core2duo
+ - PREFER_WESTMERE
+ - REQUIRE_WESTMERE
+ - PREFER_SANDBRIDGE
+ - REQUIRE_SANDYBRIDGE
+ - PREFER_IVYBRIDGE
+ - REQUIRE_IVYBRIDGE
+ - PREFER_HASWELL
+ - REQUIRE_HASWELL
+ - PREFER_BROADWELL
+ - REQUIRE_BROADWELL
+ - PREFER_NEHALEM
+ - REQUIRE_NEHALEM
+ - PREFER_PENRYN
+ - REQUIRE_PENRYN
+ - PREFER_CONROE
+ - REQUIRE_CONROE
+ - PREFER_CORE2DUO
+ - REQUIRE_CORE2DUO
+ cpu_arch:
+ type: string
+ description: >-
+ Host CPU architecture
+ required: false
+ constraints:
+ - valid_values:
+ - prefer_x86
+ - require_x86
+ - prefer_x86_64
+ - require_x86_64
+ - prefer_i686
+ - require_i686
+ - prefer_ia64
+ - require_ia64
+ - prefer_armv7
+ - require_armv7
+ - prefer_armv8
+ - require_armv8
+ - PREFER_X86
+ - REQUIRE_X86
+ - PREFER_X86_64
+ - REQUIRE_X86_64
+ - PREFER_I686
+ - REQUIRE_I686
+ - PREFER_IA64
+ - REQUIRE_IA64
+ - PREFER_ARMV7
+ - REQUIRE_ARMV7
+ - PREFER_ARMV8
+ - REQUIRE_ARMV8
+ cpu_vendor:
+ type: string
+ description: >-
+ Host CPU vendor
+ required: false
+ constraints:
+ - valid_values:
+ - prefer_intel
+ - require_intel
+ - prefer_amd
+ - requie_amd
+ - PREFER_INTEL
+ - REQUIRE_INTEL
+ - PREFER_AMD
+ - REQUIE_AMD
+ cpu_socket_count:
+ type: integer
+ description: >-
+ Number of sockets on the host
+ required: false
+ constraints:
+ - greater_than : 0
+ cpu_core_count:
+ type: integer
+ description: >-
+ Number of cores on the host
+ required: false
+ constraints:
+ - greater_than : 0
+ cpu_core_thread_count:
+ type: integer
+ description: >-
+ Number of threads per core on the host
+ required: false
+ constraints:
+ - greater_than : 0
+ cpu_feature:
+ type: list
+ entry_schema:
+ type: string
+ description: |-
+ Enumeration for CPU features.
+
+ AES- CPU supports advanced instruction set for
+ AES (Advanced Encryption Standard).
+
+ CAT- Cache Allocation Technology (CAT) allows
+ an Operating System, Hypervisor, or similar
+ system management agent to specify the amount
+ of L3 cache (currently the last-level cache
+ in most server and client platforms) space an
+ application can fill (as a hint to hardware
+ functionality, certain features such as power
+ management may override CAT settings).
+
+ CMT- Cache Monitoring Technology (CMT) allows
+ an Operating System, Hypervisor, or similar
+ system management agent to determine the
+ usage of cache based on applications running
+ on the platform. The implementation is
+ directed at L3 cache monitoring (currently
+ the last-level cache in most server and
+ client platforms).
+
+ DDIO- Intel Data Direct I/O (DDIO) enables
+ Ethernet server NICs and controllers talk
+ directly to the processor cache without a
+ detour via system memory. This enumeration
+ specifies if the VM requires a DDIO
+ capable host.
+ required: false
+ constraints:
+ -valid_values:
+ - prefer_aes
+ - require_aes
+ - prefer_cat
+ - require_cat
+ - prefer_cmt
+ - require_cmt
+ - prefer_ddio
+ - require_ddio
+ - prefer_vme
+ - require_vme
+ - prefer_de
+ - require_de
+ - prefer_pse
+ - require_pse
+ - prefer_tsc
+ - require_tsc
+ - prefer_msr
+ - require_msr
+ - prefer_pae
+ - require_pae
+ - prefer_mce
+ - require_mce
+ - prefer_cx8
+ - require_cx8
+ - prefer_apic
+ - require_apic
+ - prefer_sep
+ - require_sep
+ - prefer_mtrr
+ - require_mtrr
+ - prefer_pge
+ - require_pge
+ - prefer_mca
+ - require_mca
+ - prefer_cmov
+ - require_cmov
+ - prefer_pat
+ - require_pat
+ - prefer_pse36
+ - require_pse36
+ - prefer_clflush
+ - require_clflush
+ - prefer_dts
+ - require_dts
+ - prefer_acpi
+ - require_acpi
+ - prefer_mmx
+ - require_mmx
+ - prefer_fxsr
+ - require_fxsr
+ - prefer_sse
+ - require_sse
+ - prefer_sse2
+ - require_sse2
+ - prefer_ss
+ - require_ss
+ - prefer_ht
+ - require_ht
+ - prefer_tm
+ - require_tm
+ - prefer_ia64
+ - require_ia64
+ - prefer_pbe
+ - require_pbe
+ - prefer_rdtscp
+ - require_rdtscp
+ - prefer_pni
+ - require_pni
+ - prefer_pclmulqdq
+ - require_pclmulqdq
+ - prefer_dtes64
+ - require_dtes64
+ - prefer_monitor
+ - require_monitor
+ - prefer_ds_cpl
+ - require_ds_cpl
+ - prefer_vmx
+ - require_vmx
+ - prefer_smx
+ - require_smx
+ - prefer_est
+ - require_est
+ - prefer_tm2
+ - require_tm2
+ - prefer_ssse3
+ - require_ssse3
+ - prefer_cid
+ - require_cid
+ - prefer_fma
+ - require_fma
+ - prefer_cx16
+ - require_cx16
+ - prefer_xtpr
+ - require_xtpr
+ - prefer_pdcm
+ - require_pdcm
+ - prefer_pcid
+ - require_pcid
+ - prefer_dca
+ - require_dca
+ - prefer_sse4_1
+ - require_sse4_1
+ - prefer_sse4_2
+ - require_sse4_2
+ - prefer_x2apic
+ - require_x2apic
+ - prefer_movbe
+ - require_movbe
+ - prefer_popcnt
+ - require_popcnt
+ - prefer_tsc_deadline_timer
+ - require_tsc_deadline_timer
+ - prefer_xsave
+ - require_xsave
+ - prefer_avx
+ - require_avx
+ - prefer_f16c
+ - require_f16c
+ - prefer_rdrand
+ - require_rdrand
+ - prefer_fsgsbase
+ - require_fsgsbase
+ - prefer_bmi1
+ - require_bmi1
+ - prefer_hle
+ - require_hle
+ - prefer_avx2
+ - require_avx2
+ - prefer_smep
+ - require_smep
+ - prefer_bmi2
+ - require_bmi2
+ - prefer_erms
+ - require_erms
+ - prefer_invpcid
+ - require_invpcid
+ - prefer_rtm
+ - require_rtm
+ - prefer_mpx
+ - require_mpx
+ - prefer_rdseed
+ - require_rdseed
+ - prefer_adx
+ - require_adx
+ - prefer_smap
+ - require_smap
+ - PREFER_AES
+ - REQUIRE_AES
+ - PREFER_CAT
+ - REQUIRE_CAT
+ - PREFER_CMT
+ - REQUIRE_CMT
+ - PREFER_DDIO
+ - REQUIRE_DDIO
+ - PREFER_VME
+ - REQUIRE_VME
+ - PREFER_DE
+ - REQUIRE_DE
+ - PREFER_PSE
+ - REQUIRE_PSE
+ - PREFER_TSC
+ - REQUIRE_TSC
+ - PREFER_MSR
+ - REQUIRE_MSR
+ - PREFER_PAE
+ - REQUIRE_PAE
+ - PREFER_MCE
+ - REQUIRE_MCE
+ - PREFER_CX8
+ - REQUIRE_CX8
+ - PREFER_APIC
+ - REQUIRE_APIC
+ - PREFER_SEP
+ - REQUIRE_SEP
+ - PREFER_MTRR
+ - REQUIRE_MTRR
+ - PREFER_PGE
+ - REQUIRE_PGE
+ - PREFER_MCA
+ - REQUIRE_MCA
+ - PREFER_CMOV
+ - REQUIRE_CMOV
+ - PREFER_PAT
+ - REQUIRE_PAT
+ - PREFER_PSE36
+ - REQUIRE_PSE36
+ - PREFER_CLFLUSH
+ - REQUIRE_CLFLUSH
+ - PREFER_DTS
+ - REQUIRE_DTS
+ - PREFER_ACPI
+ - REQUIRE_ACPI
+ - PREFER_MMX
+ - REQUIRE_MMX
+ - PREFER_FXSR
+ - REQUIRE_FXSR
+ - PREFER_SSE
+ - REQUIRE_SSE
+ - PREFER_SSE2
+ - REQUIRE_SSE2
+ - PREFER_SS
+ - REQUIRE_SS
+ - PREFER_HT
+ - REQUIRE_HT
+ - PREFER_TM
+ - REQUIRE_TM
+ - PREFER_IA64
+ - REQUIRE_IA64
+ - PREFER_PBE
+ - REQUIRE_PBE
+ - PREFER_RDTSCP
+ - REQUIRE_RDTSCP
+ - PREFER_PNI
+ - REQUIRE_PNI
+ - PREFER_PCLMULQDQ
+ - REQUIRE_PCLMULQDQ
+ - PREFER_DTES64
+ - REQUIRE_DTES64
+ - PREFER_MONITOR
+ - REQUIRE_MONITOR
+ - PREFER_DS_CPL
+ - REQUIRE_DS_CPL
+ - PREFER_VMX
+ - REQUIRE_VMX
+ - PREFER_SMX
+ - REQUIRE_SMX
+ - PREFER_EST
+ - REQUIRE_EST
+ - PREFER_TM2
+ - REQUIRE_TM2
+ - PREFER_SSSE3
+ - REQUIRE_SSSE3
+ - PREFER_CID
+ - REQUIRE_CID
+ - PREFER_FMA
+ - REQUIRE_FMA
+ - PREFER_CX16
+ - REQUIRE_CX16
+ - PREFER_XTPR
+ - REQUIRE_XTPR
+ - PREFER_PDCM
+ - REQUIRE_PDCM
+ - PREFER_PCID
+ - REQUIRE_PCID
+ - PREFER_DCA
+ - REQUIRE_DCA
+ - PREFER_SSE4_1
+ - REQUIRE_SSE4_1
+ - PREFER_SSE4_2
+ - REQUIRE_SSE4_2
+ - PREFER_X2APIC
+ - REQUIRE_X2APIC
+ - PREFER_MOVBE
+ - REQUIRE_MOVBE
+ - PREFER_POPCNT
+ - REQUIRE_POPCNT
+ - PREFER_TSC_DEADLINE_TIMER
+ - REQUIRE_TSC_DEADLINE_TIMER
+ - PREFER_XSAVE
+ - REQUIRE_XSAVE
+ - PREFER_AVX
+ - REQUIRE_AVX
+ - PREFER_F16C
+ - REQUIRE_F16C
+ - PREFER_RDRAND
+ - REQUIRE_RDRAND
+ - PREFER_FSGSBASE
+ - REQUIRE_FSGSBASE
+ - PREFER_BMI1
+ - REQUIRE_BMI1
+ - PREFER_HLE
+ - REQUIRE_HLE
+ - PREFER_AVX2
+ - REQUIRE_AVX2
+ - PREFER_SMEP
+ - REQUIRE_SMEP
+ - PREFER_BMI2
+ - REQUIRE_BMI2
+ - PREFER_ERMS
+ - REQUIRE_ERMS
+ - PREFER_INVPCID
+ - REQUIRE_INVPCID
+ - PREFER_RTM
+ - REQUIRE_RTM
+ - PREFER_MPX
+ - REQUIRE_MPX
+ - PREFER_RDSEED
+ - REQUIRE_RDSEED
+ - PREFER_ADX
+ - REQUIRE_ADX
+ - PREFER_SMAP
+ - REQUIRE_SMAP
+ om_cpu_model_string:
+ type: string
+ description: >-
+ Openmano CPU model string
+ required: false
+ om_cpu_feature:
+ type: list
+ entry_schema:
+ type: string
+ description: >-
+ List of openmano CPU features
+ required: false
+
+ tosca.capabilities.nfv.riftio.sfc:
+ derived_from: tosca.capabilities.Root
+ description: >-
+ Service Function Chaining support on this VDU
+ properties:
+ sfc_type:
+ type: string
+ description: >-
+ Type of node in Service Function Chaining Architecture
+ constraints:
+ - valid_values: [unaware, classifier, sf, sff, UNAWARE, CLASSIFIER, SF, SFF]
+ default: unaware
+ sf_type:
+ type: string
+ description: >-
+ Type of Service Function.
+ NOTE- This needs to map with Service Function Type in ODL to
+ support VNFFG. Service Function Type is manadatory param in ODL
+ SFC.
+ required: false
+ tosca.capabilities.Compute.Container.Architecture:
+ derived_from: tosca.capabilities.Container
+ properties:
+ mem_page_size:
+ type: string
+ description: >-
+ Memory page allocation size. If a VM requires
+ hugepages, it should choose huge or size_2MB
+ or size_1GB. If the VM prefers hugepages, it
+ should chose prefer_huge.
+ huge/large - Require hugepages (either 2MB or 1GB)
+ normal - Does not require hugepages
+ size_2MB - Requires 2MB hugepages
+ size_1GB - Requires 1GB hugepages
+ prefer_huge - Application perfers hugepages
+ NOTE - huge and normal is only defined in standards as of
+ now.
+ required: false
+ constraints:
+ - valid_values: [normal, large, huge, size_2MB, size_1GB, prefer_huge, NORMAL,LARGE, HUGE, SIZE_2MB, SIZE_1GB, PREFER_HUGE]
+ cpu_allocation:
+ type: tosca.datatypes.compute.Container.Architecture.CPUAllocation
+ required: false
+ numa_nodes:
+ type: map
+ required: false
+ entry_schema:
+ type: tosca.datatypes.compute.Container.Architecture.NUMA
+
+
+node_types:
+ tosca.nodes.nfv.riftio.VDU1:
+ derived_from: tosca.nodes.nfv.VDU
+ properties:
+ description:
+ type: string
+ required: false
+ image:
+ description: >-
+ If an image is specified here, it is assumed that the image
+ is already present in the RO or VIM and not in the package.
+ type: string
+ required: false
+ image_checksum:
+ type: string
+ description: >-
+ Image checksum for the image in RO or VIM.
+ required: false
+ cloud_init:
+ description: >-
+ Inline cloud-init specification
+ required: false
+ type: string
+ count:
+ default: 1
+ type: integer
+ capabilities:
+ virtualLink:
+ type: tosca.capabilities.nfv.VirtualLinkable
+ monitoring_param_1:
+ type: tosca.capabilities.nfv.riftio.monitoring_param
+ mgmt_interface:
+ type: tosca.capabilities.nfv.riftio.mgmt_interface
+ monitoring_param:
+ type: tosca.capabilities.nfv.riftio.monitoring_param
+ numa_extension:
+ type: tosca.capabilities.nfv.riftio.numa_extension
+ vswitch_epa:
+ type: tosca.capabilities.nfv.riftio.vswitch_epa
+ hypervisor_epa:
+ type: tosca.capabilities.nfv.riftio.hypervisor_epa
+ host_epa:
+ type: tosca.capabilities.nfv.riftio.host_epa
+ tosca.nodes.nfv.riftio.CP1:
+ derived_from: tosca.nodes.nfv.CP
+ properties:
+ cp_type:
+ description: Type of the connection point
+ type: string
+ default: VPORT
+ constraints:
+ - valid_values: [VPORT]
+ name:
+ description: Name of the connection point
+ type: string
+ required: false
+ vdu_intf_name:
+ description: Name of the interface on VDU
+ type: string
+ vdu_intf_type:
+ description: >-
+ Specifies the type of virtual interface
+ between VM and host.
+ VIRTIO - Use the traditional VIRTIO interface.
+ PCI-PASSTHROUGH - Use PCI-PASSTHROUGH interface.
+ SR-IOV - Use SR-IOV interface.
+ E1000 - Emulate E1000 interface.
+ RTL8139 - Emulate RTL8139 interface.
+ PCNET - Emulate PCNET interface.
+ OM-MGMT - Used to specify openmano mgmt external-connection type
+ type: string
+ constraints:
+ - valid_values: [OM-MGMT, VIRTIO, E1000, SR-IOV]
+ bandwidth:
+ type: integer
+ description: Aggregate bandwidth of the NIC
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ vpci:
+ type: string
+ description: >-
+ Specifies the virtual PCI address. Expressed in
+ the following format dddd:dd:dd.d. For example
+ 0000:00:12.0. This information can be used to
+ pass as metadata during the VM creation.
+ required: false
+ capabilities:
+ sfc:
+ type: tosca.capabilities.nfv.riftio.sfc
+ tosca.nodes.nfv.riftio.VNF1:
+ derived_from: tosca.nodes.nfv.VNF
+ properties:
+ member_index:
+ type: integer
+ constraints:
+ - greater_or_equal: 1
+ description: Index of the VNF in the NS
+ required: false
+ start_by_default:
+ type: boolean
+ default: true
+ description: Start this VNF on NS instantiate
+ logo:
+ type: string
+ description: >-
+ Logo to display with the VNF in the orchestrator
+ required: false
+ capabilities:
+ mgmt_interface:
+ type: tosca.capabilities.nfv.riftio.mgmt_interface
+ monitoring_param:
+ type: tosca.capabilities.nfv.riftio.monitoring_param
+ sfc:
+ type: tosca.capabilities.nfv.riftio.sfc
+ tosca.nodes.nfv.riftio.ELAN:
+ derived_from: tosca.nodes.nfv.VL.ELAN
+ properties:
+ description:
+ type: string
+ required: false
+ network_name:
+ type: string
+ description: >-
+ Name of network in VIM account. This is used to indicate
+ pre-provisioned network name in cloud account.
+ required: false
+ root_bandwidth:
+ type: integer
+ description: >-
+ This is the aggregate bandwidth
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ leaf_bandwidth:
+ type: integer
+ description: >-
+ This is the bandwidth of branches
+ constraints:
+ - greater_or_equal: 0
+ required: false
+ tosca.nodes.nfv.riftio.FP1:
+ derived_from: tosca.nodes.nfv.FP
+ properties:
+ id:
+ type: integer
+ required: false
+ policy:
+ type: tosca.nfv.datatypes.policyType
+ required: true
+ description: policy to use to match traffic for this FP
+ path:
+ type: list
+ required: true
+ entry_schema:
+ type: tosca.nfv.datatypes.pathType
+ cp:
+ type: tosca.nfv.datatypes.pathType
+ required: true
+
+
+
+artifact_types:
+ tosca.artifacts.Deployment.riftio.cloud_init_file:
+ derived_from: tosca.artifacts.Deployment
+ file:
+ type: string
+
+ tosca.artifacts.Deployment.Image.riftio.QCOW2:
+ derived_from: tosca.artifacts.Deployment.Image.VM.QCOW2
+ image_checksum:
+ required: false
+ type: string
+
+group_types:
+ tosca.groups.nfv.VNFFG:
+ derived_from: tosca.groups.Root
+ properties:
+ vendor:
+ type: string
+ required: true
+ description: name of the vendor who generate this VNFFG
+ version:
+ type: string
+ required: true
+ description: version of this VNFFG
+ number_of_endpoints:
+ type: integer
+ required: true
+ description: count of the external endpoints included in this VNFFG
+ dependent_virtual_link:
+ type: list
+ entry_schema:
+ type: string
+ required: true
+ description: Reference to a VLD used in this Forwarding Graph
+ connection_point:
+ type: list
+ entry_schema:
+ type: string
+ required: true
+ description: Reference to Connection Points forming the VNFFG
+ constituent_vnfs:
+ type: list
+ entry_schema:
+ type: string
+ required: true
+ description: Reference to a list of VNFD used in this VNF Forwarding Graph
+ members: [ tosca.nodes.nfv.FP ]
+
+ tosca.groups.nfv.riftio.scaling:
+ derived_from: tosca.groups.Root
+ properties:
+ name:
+ type: string
+ min_instances:
+ type: integer
+ description: >-
+ Minimum instances of the scaling group which are allowed.
+ These instances are created by default when the network service
+ is instantiated.
+ max_instances:
+ type: integer
+ description: >-
+ Maximum instances of this scaling group that are allowed
+ in a single network service. The network service scaling
+ will fail, when the number of service group instances
+ exceed the max-instance-count specified.
+ cooldown_time:
+ type: integer
+ description: >-
+ The duration after a scaling-in/scaling-out action has been
+ triggered, for which there will be no further optional
+ ratio:
+ type: map
+ entry_schema:
+ type: integer
+ description: >-
+ Specify the number of instances of each VNF to instantiate
+ for a scaling action
+ members: [tosca.nodes.nfv.VNF]
+ interfaces:
+ action:
+ type: tosca.interfaces.nfv.riftio.scaling.action
+
+interface_types:
+ tosca.interfaces.nfv.riftio.scaling.action:
+ pre_scale_in:
+ description: Operation to execute before a scale in
+ post_scale_in:
+ description: Operation to execute after a scale in
+ pre_scale_out:
+ description: Operation to execute before a scale out
+ post_scale_out:
+ description: Operation to execute after a scale out
+
+policy_types:
+ tosca.policies.nfv.riftio.placement:
+ derived_from: tosca.policies.Placement
+ properties:
+ name:
+ type: string
+ description: >-
+ Place group construct to define the compute resource placement strategy
+ in cloud environment
+ requirement:
+ type: string
+ description: >-
+ This is free text space used to describe the intent/rationale
+ behind this placement group. This is for human consumption only
+ strategy:
+ type: string
+ description: >-
+ Strategy associated with this placement group
+ Following values are possible
+ COLOCATION - Colocation strategy imply intent to share the physical
+ infrastructure (hypervisor/network) among all members
+ of this group.
+ ISOLATION - Isolation strategy imply intent to not share the physical
+ infrastructure (hypervisor/network) among the members
+ of this group.
+ constraints:
+ valid_values:
+ - COLOCATION
+ - ISOLATION
+ tosca.policies.nfv.riftio.vnf_configuration:
+ derived_from: tosca.policies.Root
+ properties:
+ config:
+ type: tosca.datatypes.nfv.riftio.vnf_configuration
+ initial_config:
+ type: list
+ entry_schema:
+ type: tosca.datatypes.nfv.riftio.config_primitive
+ tosca.policies.nfv.riftio.vnf_service_primitives:
+ derived_from: tosca.policies.Root
+ properties:
+ parameter:
+ type: map
+ entry_schema:
+ type: primitive_parameter
+ tosca.policies.nfv.riftio.ns_service_primitives:
+ derived_from: tosca.policies.Root
+ properties:
+ parameter:
+ type: map
+ entry_schema:
+ type: primitive_parameter
+ parameter_group:
+ type: tosca.datatypes.nfv.riftio.primitive_parameter_group
+ description: >-
+ Grouping of parameters which are logically grouped in UI
+ required: false
+ vnf_primitive_group:
+ type: tosca.datatypes.nfv.riftio.vnf_primitive_group
+ description: >-
+ List of service primitives grouped by VNF
+ required: false
+ user_defined_script:
+ type: string
+ description: >-
+ A user defined script
+ required: false
+ tosca.policies.nfv.riftio.initial_config_primitive:
+ derived_from: tosca.policies.Root
+ properties:
+ name:
+ type: string
+ seq:
+ type: integer
+ description: >-
+ Order in which to apply, when multiple ones are defined
+ default: 0
+ constraints:
+ - greater_or_equal: 0
+ parameter:
+ type: map
+ entry_schema:
+ type: string
+ user_defined_script:
+ type: string
+ tosca.policies.nfv.riftio.users:
+ derived_from: tosca.policies.Root
+ description: >-
+ Specify list of public keys to be injected as
+ part of NS instantitation. Use default as entry,
+ to specify the key pairs for default user.
+ properties:
+ user_info:
+ type: string
+ description: >-
+ The user\'s real name
+ required: false
+ key_pairs:
+ type: map
+ description: >-
+ List of public keys for the user
+ entry_schema:
+ type: string
+ required: true
+ tosca.policies.nfv.riftio.dependency:
+ derived_from: tosca.policies.Root
+ description: >-
+ Map dependency between VDUs or VNFs
+ properties:
+ parameter:
+ type: map
+ entry_schema:
+ type: string
+ description: >-
+ Parameter and value for the config
+ tosca.nfv.datatypes.policyType:
+ properties:
+ type:
+ type: string
+ required: false
+ constraints:
+ - valid_values: [ ACL ]
+ criteria:
+ type: list
+ required: true
+ entry_schema:
+ type: tosca.nfv.datatypes.aclType
+
+
+
diff --git a/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_resource.py b/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_resource.py
index f05933b..57b0a31 100644
--- a/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_resource.py
+++ b/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_resource.py
@@ -17,7 +17,7 @@
class ToscaResource(object):
- '''Base class for YANG node type translation to RIFT.io TOSCA type.'''
+ '''Base class for YANG node type translation to RIFT.io SUBSTITUTION_MAPPINGtype.'''
# Used when creating the resource, so keeping separate
# from REQUIRED_FIELDS below
@@ -26,8 +26,10 @@
REQUIRED_FIELDS = (DESC, VERSION, VENDOR, ID) = \
('description', 'version', 'vendor', 'id')
- COMMON_FIELDS = (PATH, PORT, HOST, XPATH, TYPE, COUNT, FILE) = \
- ('path', 'port', 'host', 'xpath', 'type', 'count', 'file')
+ COMMON_FIELDS = (PATH, PORT, HOST, XPATH, TYPE, COUNT, FILE,
+ NFV_COMPUTE, HOST_EPA, VSWITCH_EPA, HYPERVISOR_EPA, GUEST_EPA) = \
+ ('path', 'port', 'host', 'xpath', 'type', 'count', 'file', 'nfv_compute',
+ 'host_epa', 'vswitch_epa', 'hypervisor_epa', 'guest_epa')
IGNORE_FIELDS = ['short_name']
@@ -41,7 +43,7 @@
MEM_VNF_INDEX_REF, VNFD_ID_REF,
MEM_VNF_INDEX, VNF_CONFIG, TYPE_Y,
USER_DEF_SCRIPT, SEQ, PARAM,
- VALUE, START_BY_DFLT,) = \
+ VALUE, START_BY_DFLT, VNFFGD, ) = \
('vld', 'nsd', 'vnfd', 'vdu', 'dashboard_params',
'config_attributes', 'config_template',
'config_type', 'config_details', 'external_interface',
@@ -49,7 +51,7 @@
'member_vnf_index_ref', 'vnfd_id_ref',
'member_vnf_index', 'vnf_configuration', 'type_yang',
'user_defined_script', 'seq', 'parameter',
- 'value', 'start_by_default',)
+ 'value', 'start_by_default', 'vnffgd',)
TOSCA_FIELDS = (DERIVED_FROM, PROPERTIES, DEFAULT, REQUIRED,
NO, CONSTRAINTS, REALTIONSHIPS,
@@ -66,17 +68,17 @@
GROUP_TYPES, POLICY_TYPES, REQUIREMENTS,
ARTIFACTS, PROPERTIES, INTERFACES,
CAPABILITIES, RELATIONSHIP,
- ARTIFACT_TYPES) = \
+ ARTIFACT_TYPES, TARGETS) = \
('data_types', 'capability_types', 'node_types',
'group_types', 'policy_types', 'requirements',
'artifacts', 'properties', 'interfaces',
'capabilities', 'relationship',
- 'artifact_types')
+ 'artifact_types', 'targets')
TOSCA_TMPL = (INPUTS, NODE_TMPL, GROUPS, POLICIES,
- METADATA, TOPOLOGY_TMPL, OUTPUTS) = \
+ METADATA, TOPOLOGY_TMPL, OUTPUTS, SUBSTITUTION_MAPPING, IMPORT) = \
('inputs', 'node_templates', 'groups', 'policies',
- 'metadata', 'topology_template', 'outputs')
+ 'metadata', 'topology_template', 'outputs', 'substitution_mappings', 'imports')
TOSCA_DERIVED = (
T_VNF_CONFIG,
@@ -91,26 +93,36 @@
T_SCALE_GRP,
T_ARTF_QCOW2,
T_INITIAL_CFG,
+ T_ARTF_CLOUD_INIT,
+ T_PLACEMENT,
+ T_ELAN,
+ T_VNFFG,
+ T_FP,
) = \
- ('tosca.datatypes.network.riftio.vnf_configuration',
+ ('tosca.policies.nfv.riftio.vnf_configuration',
'tosca.capabilities.riftio.http_endpoint_type',
'tosca.capabilities.riftio.mgmt_interface_type',
'tosca.capabilities.riftio.monitoring_param',
- 'tosca.nodes.riftio.VNF1',
- 'tosca.nodes.riftio.VDU1',
- 'tosca.nodes.riftio.CP1',
+ 'tosca.nodes.nfv.riftio.VNF1',
+ 'tosca.nodes.nfv.riftio.VDU1',
+ 'tosca.nodes.nfv.riftio.CP1',
'tosca.nodes.riftio.VL1',
'tosca.groups.riftio.ConfigPrimitives',
'tosca.policies.riftio.ScalingGroup',
'tosca.artifacts.Deployment.Image.riftio.QCOW2',
- 'tosca.policies.riftio.InitialConfigPrimitive'
+ 'tosca.policies.nfv.riftio.initial_config_primitive',
+ 'tosca.artifacts.Deployment.riftio.cloud_init_file',
+ 'tosca.policies.nfv.riftio.placement',
+ 'tosca.nodes.nfv.riftio.ELAN',
+ 'tosca.groups.nfv.VNFFG',
+ 'tosca.nodes.nfv.riftio.FP1',
)
SUPPORT_FILES = ( SRC, DEST, EXISTING) = \
('source', 'destination', 'existing')
- SUPPORT_DIRS = (IMAGE_DIR, SCRIPT_DIR,) = \
- ('images', 'scripts',)
+ SUPPORT_DIRS = (IMAGE_DIR, SCRIPT_DIR, CLOUD_INIT_DIR) = \
+ ('images', 'scripts','cloud_init')
def __init__(self,
log,
diff --git a/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_template.py b/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_template.py
index 7c31df5..95f2cb2 100644
--- a/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_template.py
+++ b/common/python/rift/mano/yang_translator/rwmano/syntax/tosca_template.py
@@ -36,6 +36,15 @@
self.log.debug(_('Converting translated output to tosca template.'))
templates = {}
+ vnfd_templates = {}
+
+ for resource in self.resources:
+ if resource.type == 'vnfd':
+ tmpl = resource.generate_tosca()
+ tmpl = resource.generate_tosca_template(tmpl)
+ self.log.debug(_("TOSCA template generated for {0}:\n{1}").
+ format(resource.name, tmpl))
+ vnfd_templates[resource.name] = tmpl
for resource in self.resources:
# Each NSD should generate separate templates
@@ -49,6 +58,14 @@
if len(files):
templates[resource.name][self.FILES] = files
+ for resource in self.resources:
+ if resource.type == 'vnfd':
+ tmpl = vnfd_templates[resource.name]
+ templates[resource.name] = {self.TOSCA: self.output_to_yaml(tmpl)}
+ files = resource.get_supporting_files()
+ if len(files):
+ templates[resource.name][self.FILES] = files
+
return templates
def represent_ordereddict(self, dumper, data):
@@ -66,6 +83,7 @@
ToscaResource.REQUIREMENTS,ToscaResource.ARTIFACTS,
ToscaResource.INTERFACES]
new_node = OrderedDict()
+ self.log.debug("Node to oder: {}".format(node))
for ent in order:
if ent in node:
new_node.update({ent: node.pop(ent)})
@@ -87,10 +105,18 @@
else:
return nodes
+ def ordered_nodes_sub_mapping(self, nodes):
+ new_nodes = OrderedDict()
+ if isinstance(nodes, dict):
+ for name, node in nodes.items():
+ new_nodes.update({name: node})
+ return new_nodes
+ else:
+ return nodes
+
def output_to_yaml(self, tosca):
self.log.debug(_('Converting translated output to yaml format.'))
dict_output = OrderedDict()
-
dict_output.update({'tosca_definitions_version':
tosca['tosca_definitions_version']})
# Description
@@ -106,6 +132,9 @@
if ToscaResource.METADATA in tosca:
dict_output.update({ToscaResource.METADATA:
tosca[ToscaResource.METADATA]})
+ if ToscaResource.IMPORT in tosca:
+ dict_output.update({ToscaResource.IMPORT:
+ tosca[ToscaResource.IMPORT]})
# Add all types
types_list = [ToscaResource.DATA_TYPES, ToscaResource.CAPABILITY_TYPES,
@@ -122,9 +151,14 @@
if ToscaResource.TOPOLOGY_TMPL in tosca:
tmpl = OrderedDict()
for typ in tosca[ToscaResource.TOPOLOGY_TMPL]:
- tmpl.update({typ:
- self.ordered_nodes(
- tosca[ToscaResource.TOPOLOGY_TMPL][typ])})
+ if typ != ToscaResource.SUBSTITUTION_MAPPING:
+ tmpl.update({typ:
+ self.ordered_nodes(
+ tosca[ToscaResource.TOPOLOGY_TMPL][typ])})
+ else:
+ tmpl.update({typ:
+ self.ordered_nodes_sub_mapping(
+ tosca[ToscaResource.TOPOLOGY_TMPL][typ])})
dict_output.update({ToscaResource.TOPOLOGY_TMPL: tmpl})
yaml.add_representer(OrderedDict, self.represent_ordereddict)
diff --git a/common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py b/common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py
index f0a6866..707ab7f 100644
--- a/common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py
+++ b/common/python/rift/mano/yang_translator/rwmano/translate_descriptors.py
@@ -104,10 +104,11 @@
return types_map
- def __init__(self, log, yangs, tosca_template):
+ def __init__(self, log, yangs, tosca_template, vnfd_files=None):
self.log = log
self.yangs = yangs
self.tosca_template = tosca_template
+ self.vnfd_files = vnfd_files
# list of all TOSCA resources generated
self.tosca_resources = []
self.metadata = {}
@@ -143,27 +144,30 @@
def _translate_yang(self):
self.log.debug(_('Translating the descriptors.'))
- for nsd in self.yangs[self.NSD]:
- self.log.debug(_("Translate descriptor of type nsd: {}").
- format(nsd))
- tosca_node = TranslateDescriptors. \
- YANG_TO_TOSCA_TYPE[self.NSD](
- self.log,
- nsd.pop(ToscaResource.NAME),
- self.NSD,
- nsd)
- self.tosca_resources.append(tosca_node)
+ if self.NSD in self.yangs:
+ for nsd in self.yangs[self.NSD]:
+ self.log.debug(_("Translate descriptor of type nsd: {}").
+ format(nsd))
+ tosca_node = TranslateDescriptors. \
+ YANG_TO_TOSCA_TYPE[self.NSD](
+ self.log,
+ nsd.pop(ToscaResource.NAME),
+ self.NSD,
+ nsd,
+ self.vnfd_files)
+ self.tosca_resources.append(tosca_node)
- for vnfd in self.yangs[self.VNFD]:
- self.log.debug(_("Translate descriptor of type vnfd: {}").
- format(vnfd))
- tosca_node = TranslateDescriptors. \
- YANG_TO_TOSCA_TYPE[self.VNFD](
- self.log,
- vnfd.pop(ToscaResource.NAME),
- self.VNFD,
- vnfd)
- self.tosca_resources.append(tosca_node)
+ if self.VNFD in self.yangs:
+ for vnfd in self.yangs[self.VNFD]:
+ self.log.debug(_("Translate descriptor of type vnfd: {}").
+ format(vnfd))
+ tosca_node = TranslateDescriptors. \
+ YANG_TO_TOSCA_TYPE[self.VNFD](
+ self.log,
+ vnfd.pop(ToscaResource.NAME),
+ self.VNFD,
+ vnfd)
+ self.tosca_resources.append(tosca_node)
# First translate VNFDs
for node in self.tosca_resources:
diff --git a/common/python/rift/mano/yang_translator/rwmano/yang/yang_nsd.py b/common/python/rift/mano/yang_translator/rwmano/yang/yang_nsd.py
index 491bd86..d28b3e1 100644
--- a/common/python/rift/mano/yang_translator/rwmano/yang/yang_nsd.py
+++ b/common/python/rift/mano/yang_translator/rwmano/yang/yang_nsd.py
@@ -21,6 +21,7 @@
from rift.mano.yang_translator.rwmano.syntax.tosca_resource \
import ToscaResource
from rift.mano.yang_translator.rwmano.yang.yang_vld import YangVld
+from collections import OrderedDict
TARGET_CLASS_NAME = 'YangNsd'
@@ -49,7 +50,8 @@
log,
name,
type_,
- yang):
+ yang,
+ vnfd_files):
super(YangNsd, self).__init__(log,
name,
type_,
@@ -57,10 +59,20 @@
self.props = {}
self.inputs = []
self.vnfds = {}
- self.vlds = []
+ self.vlds = {}
self.conf_prims = []
self.scale_grps = []
self.initial_cfg = []
+ self.placement_groups = []
+ self.vnf_id_to_vnf_map = {}
+ self.vnfd_files = vnfd_files
+ self.vld_to_vnf_map = {}
+ self.vnf_to_vld_map = {}
+ self._vnf_vld_conn_point_map = {}
+ self.vnffgds = {}
+ self.forwarding_paths = {}
+ self.substitution_mapping_forwarder = []
+ self.vnfd_sfc_map = None
def handle_yang(self, vnfds):
self.log.debug(_("Process NSD desc {0}: {1}").
@@ -85,6 +97,7 @@
vnfd_id = cvnfd.pop(self.VNFD_ID_REF)
for vnfd in vnfds:
if vnfd.type == self.VNFD and vnfd.id == vnfd_id:
+ self.vnf_id_to_vnf_map[vnfd_id] = vnfd.name
self.vnfds[cvnfd.pop(self.MEM_VNF_INDEX)] = vnfd
if self.START_BY_DFLT in cvnfd:
vnfd.props[self.START_BY_DFLT] = \
@@ -160,7 +173,244 @@
self.log.warn(_("{0}, Did not process all fields for {1}").
format(self, dic))
self.log.debug(_("{0}, Initial config {1}").format(self, icp))
- self.initial_cfg.append(icp)
+ self.initial_cfg.append({self.PROPERTIES : icp})
+
+ def process_vld(vld, dic):
+ vld_conf = {}
+ vld_prop = {}
+ ip_profile_vld = None
+ vld_name = None
+ if 'ip_profile_ref' in vld:
+ ip_profile_name = vld['ip_profile_ref']
+ if 'ip_profiles' in dic:
+ for ip_prof in dic['ip_profiles']:
+ if ip_profile_name == ip_prof['name']:
+ ip_profile_vld = ip_prof
+ if 'name' in vld:
+ vld_name = vld['name'].replace('-','_').replace(' ','')
+ if 'description' in vld:
+ vld_conf['description'] = vld['description']
+ if 'vendor' in vld:
+ vld_conf['vendor'] = vld['vendor']
+ if ip_profile_vld:
+ if 'ip_profile_params' in ip_profile_vld:
+ ip_param = ip_profile_vld['ip_profile_params']
+ if 'gateway_address' in ip_param:
+ vld_conf['gateway_ip'] = ip_param['gateway_address']
+ if 'subnet_address' in ip_param:
+ vld_conf['cidr'] = ip_param['subnet_address']
+ if 'ip_version' in ip_param:
+ vld_conf['ip_version'] = ip_param['ip_version'].replace('ipv','')
+
+ if vld_name:
+ vld_prop = {vld_name :
+ {
+ 'type': self.T_ELAN,
+ self.PROPERTIES : vld_conf
+ }}
+ self.vlds[vld_name] = { 'type': self.T_ELAN,
+ self.PROPERTIES : vld_conf
+ }
+
+ self.vld_to_vnf_map[vld_name] = []
+ if 'vnfd_connection_point_ref' in vld:
+ for vnfd_ref in vld['vnfd_connection_point_ref']:
+ vnf_name = self.vnf_id_to_vnf_map[vnfd_ref['vnfd_id_ref']]
+ if vnf_name in self.vnf_to_vld_map:
+ self.vnf_to_vld_map[vnf_name].append(vld_name)
+ self._vnf_vld_conn_point_map[vnf_name].\
+ append((vld_name ,vnfd_ref['vnfd_connection_point_ref']))
+ else:
+ self.vnf_to_vld_map[vnf_name] = []
+ self._vnf_vld_conn_point_map[vnf_name] = []
+ self.vnf_to_vld_map[vnf_name].append(vld_name)
+ self._vnf_vld_conn_point_map[vnf_name].\
+ append((vld_name ,vnfd_ref['vnfd_connection_point_ref']))
+
+ def process_placement_group(placement_groups):
+ for i in range(0, len(placement_groups)):
+ placement_group = placement_groups[i]
+ pg_name = "placement_{0}".format(i)
+ pg_config = {}
+ targets = []
+ if 'name' in placement_group:
+ pg_config['name'] = placement_group['name']
+ if 'requirement' in placement_group:
+ pg_config['requirement'] = placement_group['requirement']
+ if 'strategy' in placement_group:
+ pg_config['strategy'] = placement_group['strategy']
+ if 'member_vnfd' in placement_group:
+ for member_vnfd in placement_group['member_vnfd']:
+ targets.append(self.vnf_id_to_vnf_map[member_vnfd['vnfd_id_ref']])
+ placement = { pg_name : {
+ 'type': self.T_PLACEMENT,
+ self.PROPERTIES: pg_config,
+ self.TARGETS : str(targets)
+ }
+ }
+ self.placement_groups.append(placement)
+
+ def process_vnffgd(vnffgs, dic):
+ associated_cp_names = []
+ all_cp_names = []
+ vnfd_sfc_map = {}
+
+ conn_point_to_conection_node = {}
+ conn_point_to_vnf_name_map = {}
+
+ unigue_id_forwarder_path_map = OrderedDict()
+ forwarder_name_to_constitent_vnf_map = OrderedDict()
+ unique_id_classifier_map = OrderedDict()
+ fp_path_count = 1
+ forwarder_count = 1
+
+ vnffg_to_unique_id_rsp_map = OrderedDict()
+ vnffg_to_unique_id_classifier_map = OrderedDict()
+ vnffg_to_associated_cp_names = OrderedDict()
+ rsp_associated_cp_names = OrderedDict()
+ vnffg_to_forwarder_map = OrderedDict()
+ for vnffg in vnffgs:
+ unique_id_rsp_map = {}
+ for rs in vnffg['rsp']:
+ unique_id_rsp_map[str(rs['id'])] = rs
+ for class_identifier in vnffg['classifier']:
+ unique_id_classifier_map[str(class_identifier['rsp_id_ref'])] = class_identifier
+ associated_cp_names.append(class_identifier['vnfd_connection_point_ref'])
+ all_cp_names.append(class_identifier['vnfd_connection_point_ref'])
+ conn_point_to_vnf_name_map[class_identifier['vnfd_connection_point_ref']] = self.vnf_id_to_vnf_map[class_identifier['vnfd_id_ref']]
+ vnfd_sfc_map[self.vnf_id_to_vnf_map[class_identifier['vnfd_id_ref']]] = class_identifier['vnfd_connection_point_ref']
+
+ rsp_associated_cp_names[str(class_identifier['rsp_id_ref'])] = class_identifier['vnfd_connection_point_ref']
+
+ vnffg_to_unique_id_rsp_map[vnffg['name']] = unique_id_rsp_map
+ vnffg_to_forwarder_map[vnffg['name']] = []
+
+ for vnffg in vnffgs:
+ prop = {}
+ fp_members = []
+
+
+ prop['type'] = self.T_VNFFG
+ prop[self.DESC] = "Test"
+ prop[self.PROPERTIES] = {}
+ if 'vendor' in vnffg:
+ prop[self.PROPERTIES]['vendor'] = vnffg['vendor']
+ if 'name' in vnffg:
+ self.vnffgds[vnffg['name']] = prop
+
+ for rs_id, rs in vnffg_to_unique_id_rsp_map[vnffg['name']].items():
+ associated_cp_node_names = []
+ associated_vnf_names = []
+ number_of_endpoints = 0
+ if 'vnfd_connection_point_ref' in rs:
+ number_of_endpoints = number_of_endpoints + len(rs['vnfd_connection_point_ref'])
+ for vnf in rs['vnfd_connection_point_ref']:
+ associated_vnf_names.append(str(self.vnf_id_to_vnf_map[vnf['vnfd_id_ref']]))
+ associated_cp_names.append(vnf['vnfd_connection_point_ref'])
+ all_cp_names.append(vnf['vnfd_connection_point_ref'])
+ conn_point_to_vnf_name_map[vnf['vnfd_connection_point_ref']] = self.vnf_id_to_vnf_map[vnf['vnfd_id_ref']]
+ if "forwarder{}".format(fp_path_count) not in forwarder_name_to_constitent_vnf_map:
+ forwarder_name_to_constitent_vnf_map["forwarder{}".format(fp_path_count)] = associated_vnf_names
+ vnffg_to_forwarder_map[vnffg['name']].append("forwarder{}".format(fp_path_count))
+ fp_path_count = fp_path_count + 1
+
+ associated_cp_names = list(set(associated_cp_names))
+ for cp_name in associated_cp_names:
+ for idx, vnfd in self.vnfds.items():
+ for vdu in vnfd.vdus:
+ if cp_name == rsp_associated_cp_names[rs_id]:
+ if cp_name in vdu.conn_point_to_conection_node:
+ associated_cp_node_names.append(vdu.conn_point_to_conection_node[cp_name])
+ #conn_point_to_conection_node[cp_name] = vdu.conn_point_to_conection_node[cp_name]
+
+ for cp_name in all_cp_names:
+ for idx, vnfd in self.vnfds.items():
+ for vdu in vnfd.vdus:
+ if cp_name in vdu.conn_point_to_conection_node:
+ conn_point_to_conection_node[cp_name] = vdu.conn_point_to_conection_node[cp_name]
+
+ if len(associated_vnf_names) > 0:
+ associated_vnf_names = list(set(associated_vnf_names))
+ vnf_str = ", ".join(associated_vnf_names)
+ prop[self.PROPERTIES]['constituent_vnfs'] = "[{}]".format(vnf_str)
+ if len(associated_cp_node_names) > 0:
+ associated_cp_node_names = list(set(associated_cp_node_names))
+ connection_point_str = ", ".join(associated_cp_node_names)
+ prop[self.PROPERTIES]['connection_point'] = "[{}]".format(", ".join(associated_cp_node_names))
+
+ prop[self.PROPERTIES]['number_of_endpoints'] = number_of_endpoints
+ fp_name = "Forwarding_path{}".format(forwarder_count)
+ unigue_id_forwarder_path_map[fp_name] = rs_id
+ fp_members.append(fp_name)
+ forwarder_count = forwarder_count + 1
+
+ if len(fp_members) > 0:
+ prop['members'] = []
+ for fp in fp_members:
+ prop['members'].append(fp)
+
+ fp_count = 1
+ for fp, idx in unigue_id_forwarder_path_map.items():
+ for vnffg_name, unique_id_rsp_map in vnffg_to_unique_id_rsp_map.items():
+ if idx in unique_id_rsp_map:
+ prop = {}
+ prop['type'] = self.T_FP
+ prop[self.PROPERTIES] = {}
+ prop[self.PROPERTIES][self.DESC] = "Forwarder"
+ prop[self.PROPERTIES]['policy'] = {}
+ prop[self.PROPERTIES]['policy']['type'] = 'ACL'
+ prop[self.PROPERTIES]['policy']['criteria'] = []
+
+ prop[self.PROPERTIES]['path'] = []
+
+ rsp = unique_id_rsp_map[idx]
+ classifier = unique_id_classifier_map[idx]
+
+ for match in classifier['match_attributes']:
+ match_prop = {}
+ if 'source_port' in match:
+ port = "'{}'".format((match['source_port']))
+ prop[self.PROPERTIES]['policy']['criteria'].append({'source_port_range': port})
+ if 'destination_port' in match:
+ port = "'f'{}''".format((match['destination_port']))
+ prop[self.PROPERTIES]['policy']['criteria'].append({'destination_port_range': '5006'})
+ if 'ip_proto' in match:
+ port = match['ip_proto']
+ prop[self.PROPERTIES]['policy']['criteria'].append({'ip_proto': port})
+ if 'destination_ip_address' in match:
+ port = "'{}'".format((match['destination_ip_address']))
+ prop[self.PROPERTIES]['policy']['criteria'].append({'ip_dst_prefix': port})
+
+ if 'vnfd_connection_point_ref' in classifier:
+ if classifier['vnfd_connection_point_ref'] in conn_point_to_vnf_name_map:
+ if 'cp' not in prop[self.PROPERTIES]:
+ prop[self.PROPERTIES]['cp'] = {}
+ prop[self.PROPERTIES]['cp']['forwarder'] = conn_point_to_vnf_name_map[classifier['vnfd_connection_point_ref']]
+ prop[self.PROPERTIES]['cp']['capability'] = conn_point_to_conection_node[classifier['vnfd_connection_point_ref']]
+
+ for fp, vnf_list in forwarder_name_to_constitent_vnf_map.items():
+ for vnf in vnf_list:
+ for cp, vnf_name in conn_point_to_vnf_name_map.items():
+ if vnf == vnf_name:
+ self.substitution_mapping_forwarder.append((vnf, fp, conn_point_to_conection_node[cp]))
+
+ visited_forwarder = []
+ visited_path = None
+ for path, vnfs in forwarder_name_to_constitent_vnf_map.items():
+ for vnf in vnfs:
+ if (vnf not in visited_forwarder) and (path in vnffg_to_forwarder_map[vnffg_name]):
+ path_prop = {}
+ path_prop['forwarder'] = vnf
+ path_prop['capability'] = path
+ prop[self.PROPERTIES]['path'].append(path_prop)
+ visited_forwarder.append(vnf)
+ visited_path = path
+ forwarder_name_to_constitent_vnf_map.pop(visited_path)
+
+ self.forwarding_paths["Forwarding_path{}".format(fp_count)] = prop
+ fp_count = fp_count +1
+
+ self.vnfd_sfc_map = vnfd_sfc_map
dic = deepcopy(self.yang)
try:
@@ -177,15 +427,20 @@
# Process VLDs
if self.VLD in dic:
for vld_dic in dic.pop(self.VLD):
- vld = YangVld(self.log, vld_dic.pop(self.NAME),
- self.VLD, vld_dic)
- vld.process_vld(self.vnfds)
- self.vlds.append(vld)
+ process_vld(vld_dic, dic)
+ #self.vlds.append(vld)
+
+ #Process VNFFG
+ if self.VNFFGD in dic:
+ process_vnffgd(dic[self.VNFFGD], dic)
+
+
+ #if self.
# Process config primitives
if self.CONF_PRIM in dic:
for cprim in dic.pop(self.CONF_PRIM):
- conf_prim = {self.NAME: cprim.pop(self.NAME)}
+ conf_prim = {self.NAME: cprim.pop(self.NAME), self.DESC : 'TestDescription'}
if self.USER_DEF_SCRIPT in cprim:
conf_prim[self.USER_DEF_SCRIPT] = \
cprim.pop(self.USER_DEF_SCRIPT)
@@ -212,6 +467,10 @@
for param in dic.pop(self.INPUT_PARAM_XPATH):
process_input_param(param)
+ if 'placement_groups' in dic:
+ process_placement_group(dic['placement_groups'])
+
+
self.remove_ignored_fields(dic)
if len(dic):
self.log.warn(_("{0}, Did not process the following for "
@@ -226,13 +485,14 @@
raise ValidationError(message=err_msg)
def generate_tosca_type(self):
+
self.log.debug(_("{0} Generate tosa types").
format(self))
tosca = {}
- tosca[self.DATA_TYPES] = {}
- tosca[self.NODE_TYPES] = {}
-
+ #tosca[self.DATA_TYPES] = {}
+ #tosca[self.NODE_TYPES] = {}
+ return tosca
for idx, vnfd in self.vnfds.items():
tosca = vnfd.generate_tosca_type(tosca)
@@ -287,20 +547,25 @@
def generate_tosca_template(self, tosca):
self.log.debug(_("{0}, Generate tosca template").
format(self, tosca))
-
# Add the standard entries
tosca['tosca_definitions_version'] = \
- 'tosca_simple_profile_for_nfv_1_0_0'
+ 'tosca_simple_profile_for_nfv_1_0'
tosca[self.DESC] = self.props[self.DESC]
tosca[self.METADATA] = {
'ID': self.name,
self.VENDOR: self.props[self.VENDOR],
self.VERSION: self.props[self.VERSION],
}
+ if len(self.vnfd_files) > 0:
+ tosca[self.IMPORT] = []
+ imports = []
+ for vnfd_file in self.vnfd_files:
+ tosca[self.IMPORT].append('"{0}.yaml"'.format(vnfd_file))
tosca[self.TOPOLOGY_TMPL] = {}
# Add input params
+ '''
if len(self.inputs):
if self.INPUTS not in tosca[self.TOPOLOGY_TMPL]:
tosca[self.TOPOLOGY_TMPL][self.INPUTS] = {}
@@ -309,15 +574,50 @@
self.DESC:
'Translated from YANG'}}
tosca[self.TOPOLOGY_TMPL][self.INPUTS] = entry
-
+ '''
tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL] = {}
# Add the VNFDs and VLDs
for idx, vnfd in self.vnfds.items():
- vnfd.generate_vnf_template(tosca, idx)
+ #vnfd.generate_vnf_template(tosca, idx)
+ node = {
+ 'type' : vnfd.vnf_type,
+ self.PROPERTIES : {
+ self.ID : idx,
+ self.VENDOR : self.props[self.VENDOR],
+ self.VERSION : self.props[self.VERSION]
+ }
+ }
+ if vnfd.name in self.vnf_to_vld_map:
+ vld_list = self.vnf_to_vld_map[vnfd.name]
+ node[self.REQUIREMENTS] = []
+ for vld_idx in range(0, len(vld_list)):
+ vld_link_name = "{0}{1}".format("virtualLink", vld_idx + 1)
+ vld_prop = {}
+ vld_prop[vld_link_name] = vld_list[vld_idx]
+ node[self.REQUIREMENTS].append(vld_prop)
+ if vnfd.name in self._vnf_vld_conn_point_map:
+ vnf_vld_list = self._vnf_vld_conn_point_map[vnfd.name]
+ for vnf_vld in vnf_vld_list:
+ vnfd.generate_vld_link(vld_link_name, vnf_vld[1])
- for vld in self.vlds:
- vld.generate_tosca_template(tosca)
+ for sub_mapping in self.substitution_mapping_forwarder:
+ if sub_mapping[0] == vnfd.name:
+ vnfd.generate_forwarder_sub_mapping(sub_mapping)
+
+ for vnfd_name, cp_name in self.vnfd_sfc_map.items():
+ if vnfd.name == vnfd_name:
+ vnfd.generate_sfc_link(cp_name)
+
+
+
+ tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vnfd.name] = node
+
+ for vld_node_name in self.vlds:
+ tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vld_node_name] = self.vlds[vld_node_name]
+
+ for fp_name, fp in self.forwarding_paths.items():
+ tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][fp_name] = fp
# add the config primitives
if len(self.conf_prims):
@@ -337,8 +637,8 @@
conf_prims[self.PROPERTIES] = {
self.PRIMITIVES: prims
}
-
- tosca[self.TOPOLOGY_TMPL][self.GROUPS][self.CONF_PRIM] = conf_prims
+ conf_prims[self.DESC] = 'Test'
+ #tosca[self.TOPOLOGY_TMPL][self.GROUPS][self.CONF_PRIM] = conf_prims
# Add the scale group
@@ -361,33 +661,45 @@
tosca[self.TOPOLOGY_TMPL][self.POLICIES] = []
for icp in self.initial_cfg:
- icpt = {
- self.TYPE: self.T_INITIAL_CFG,
- }
- icpt.update(icp)
- tosca[self.TOPOLOGY_TMPL][self.POLICIES].append({
- self.INITIAL_CFG: icpt
- })
+ if len(tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL]) > 0:
+ node_name = list(tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL].keys())[0]
+ icpt = {
+ self.TYPE: self.T_INITIAL_CFG,
+ self.TARGETS : "[{0}]".format(node_name)
+ }
+ icpt.update(icp)
+ tosca[self.TOPOLOGY_TMPL][self.POLICIES].append({
+ self.INITIAL_CFG: icpt
+ })
+
+ if len(self.placement_groups) > 0:
+ if self.POLICIES not in tosca[self.TOPOLOGY_TMPL]:
+ tosca[self.TOPOLOGY_TMPL][self.POLICIES] = []
+
+ for placment_group in self.placement_groups:
+ tosca[self.TOPOLOGY_TMPL][self.POLICIES].append(placment_group)
+
+ if len(self.vnffgds) > 0:
+ if self.GROUPS not in tosca[self.TOPOLOGY_TMPL]:
+ tosca[self.TOPOLOGY_TMPL][self.GROUPS] = {}
+ for vnffgd_name in self.vnffgds:
+ tosca[self.TOPOLOGY_TMPL][self.GROUPS][vnffgd_name] = self.vnffgds[vnffgd_name]
+
return tosca
def get_supporting_files(self):
files = []
-
- for vnfd in self.vnfds.values():
- f = vnfd.get_supporting_files()
- if f and len(f):
- files.extend(f)
-
# Get the config files for initial config
for icp in self.initial_cfg:
- if self.USER_DEF_SCRIPT in icp:
- script = os.path.basename(icp[self.USER_DEF_SCRIPT])
- files.append({
- self.TYPE: 'script',
- self.NAME: script,
- self.DEST: "{}/{}".format(self.SCRIPT_DIR, script),
- })
+ if 'properties' in icp:
+ if 'user_defined_script' in icp['properties']:
+ script = os.path.basename(icp['properties']['user_defined_script'])
+ files.append({
+ self.TYPE: 'script',
+ self.NAME: script,
+ self.DEST: "{}/{}".format(self.SCRIPT_DIR, script),
+ })
# TODO (pjoseph): Add support for config scripts,
# charms, etc
diff --git a/common/python/rift/mano/yang_translator/rwmano/yang/yang_vdu.py b/common/python/rift/mano/yang_translator/rwmano/yang/yang_vdu.py
index 7d095c1..2d82872 100644
--- a/common/python/rift/mano/yang_translator/rwmano/yang/yang_vdu.py
+++ b/common/python/rift/mano/yang_translator/rwmano/yang/yang_vdu.py
@@ -56,6 +56,15 @@
'storage_gb': ' GB',
}
+ TOSCA_MEM_SIZE = {
+ 'LARGE': 'huge',
+ 'SMALL': 'normal',
+ 'SIZE_2MB': 'size_2MB',
+ 'SIZE_1GB': 'size_1GB',
+ 'PREFER_LARGE': 'prefer_huge'
+
+ }
+
def __init__(self,
log,
name,
@@ -69,8 +78,16 @@
self.props = {}
self.ext_cp = []
self.int_cp = []
- self.image = None
+ self.image = None
self.cloud_init_file = None
+ self.host_epa = None
+ self.vswitch_epa = None
+ self.hypervisor_epa = None
+ self.guest_epa = None
+ self.cp_name_to_cp_node = {}
+ self.pinning_epa_prop = {}
+ self.mem_page_guest_epa = None
+ self.conn_point_to_conection_node = {}
def process_vdu(self):
self.log.debug(_("Process VDU desc {0}: {1}").format(self.name,
@@ -88,9 +105,9 @@
self.id = vdu[self.ID]
if self.VM_FLAVOR in vdu_dic:
- vdu[self.HOST] = {}
+ vdu[self.NFV_COMPUTE] = {}
for key, value in vdu_dic.pop(self.VM_FLAVOR).items():
- vdu[self.HOST][self.VM_FLAVOR_MAP[key]] = "{}{}". \
+ vdu[self.NFV_COMPUTE][self.VM_FLAVOR_MAP[key]] = "{}{}". \
format(value, self.VM_SIZE_UNITS_MAP[key])
if self.EXT_INTF in vdu_dic:
@@ -103,7 +120,115 @@
format(self, cp, ext_intf))
self.ext_cp.append(cp)
+ if self.HOST_EPA in vdu_dic:
+ host_epa = vdu_dic.pop(self.HOST_EPA)
+ host_epa_prop = {}
+ self.host_epa = host_epa
+ '''
+ if 'cpu_model' in host_epa:
+ host_epa_prop['cpu_model'] = host_epa['cpu_model'].lower()
+ if 'cpu_arch' in host_epa:
+ host_epa_prop['cpu_arch'] = host_epa['cpu_arch'].lower()
+ if 'cpu_vendor' in host_epa:
+ host_epa_prop['cpu_vendor'] = host_epa['cpu_vendor'].lower()
+ if 'cpu_socket_count' in host_epa:
+ host_epa_prop['cpu_socket_count'] = host_epa['cpu_socket_count']
+ if 'cpu_core_count' in host_epa:
+ host_epa_prop['cpu_core_count'] = host_epa['cpu_core_count']
+ if 'cpu_core_thread_count' in host_epa:
+ host_epa_prop['cpu_core_thread_count'] = host_epa['cpu_core_thread_count']
+ if 'om_cpu_model_string' in host_epa:
+ host_epa_prop['om_cpu_model_string'] = host_epa['om_cpu_model_string']
+ if 'cpu_feature' in host_epa:
+ host_epa_prop['cpu_feature'] = []
+ for cpu_feature in host_epa['cpu_feature']:
+ cpu_feature_prop = {}
+ cpu_feature_prop['feature'] = cpu_feature['feature'].lower()
+ host_epa_prop['cpu_feature'] .append(cpu_feature_prop)
+
+ if 'om_cpu_feature' in host_epa:
+ host_epa_prop['om_cpu_feature'] = []
+ for cpu_feature in host_epa['om_cpu_feature']:
+ om_cpu_feature_prop = {}
+ om_cpu_feature_prop['feature'] = cpu_feature
+ host_epa_prop['om_cpu_feature'].append(om_cpu_feature_prop)
+ self.host_epa = host_epa
+ '''
+ # We might have to re write this piece of code, there are mismatch in
+ # enum names. Its all capital in RIFT yang and TOSCA
+ if self.VSWITCH_EPA in vdu_dic:
+ vswitch_epa = vdu_dic.pop(self.VSWITCH_EPA)
+ self.vswitch_epa = vswitch_epa
+ if self.HYPERVISOR_EPA in vdu_dic:
+ hypervisor_epa = vdu_dic.pop(self.HYPERVISOR_EPA)
+ hypervisor_epa_prop = {}
+
+ if 'type_yang' in hypervisor_epa:
+ hypervisor_epa_prop['type'] = hypervisor_epa['type_yang']
+ if 'version' in hypervisor_epa:
+ hypervisor_epa_prop['version'] = str(hypervisor_epa['version'])
+ else:
+ hypervisor_epa_prop['version'] = '1'
+ self.hypervisor_epa = hypervisor_epa_prop
+
+ if self.GUEST_EPA in vdu_dic:
+ guest_epa = vdu_dic[self.GUEST_EPA]
+ guest_epa_prop = {}
+
+ # This is a hack. I have to rewrite this. I have got this quick to working
+ # 'ANY' check should be added in riftio common file. Its not working for some reason. Will fix.
+
+ if 'cpu_pinning_policy' in guest_epa and guest_epa['cpu_pinning_policy'] != 'ANY':
+ self.pinning_epa_prop['cpu_affinity'] = guest_epa['cpu_pinning_policy'].lower()
+ if 'cpu_thread_pinning_policy' in guest_epa:
+ self.pinning_epa_prop['thread_allocation'] = guest_epa['cpu_thread_pinning_policy'].lower()
+ if 'mempage_size' in guest_epa:
+ self.mem_page_guest_epa = self.TOSCA_MEM_SIZE[guest_epa['mempage_size']]
+
+ if 'numa_node_policy' in guest_epa:
+ num_node_policy = guest_epa['numa_node_policy']
+ if 'node_cnt' in num_node_policy:
+ guest_epa_prop['node_cnt'] = num_node_policy['node_cnt']
+ if 'mem_policy' in num_node_policy:
+ guest_epa_prop['mem_policy'] = num_node_policy['mem_policy']
+ if 'node' in num_node_policy:
+ nodes = []
+ for node in num_node_policy['node']:
+ node_prop = {}
+ if 'id' in node:
+ node_prop['id'] = node['id']
+ if 'vcpu' in node:
+ vc =[]
+ for vcp in node['vcpu']:
+ vc.append(vcp['id'])
+
+ node_prop['vcpus'] = vc
+ if 'memory_mb' in node:
+ node_prop['mem_size'] = "{} MB".format(node['memory_mb'])
+ # om_numa_type generation
+
+ if 'num_cores' in node:
+ node_prop['om_numa_type'] = 'num_cores'
+ node_prop['num_cores'] = node['num_cores']
+ elif 'paired_threads' in node:
+ node_prop['om_numa_type'] = 'paired-threads'
+ node_prop['paired_threads'] = node['paired_threads']
+ elif 'threads]' in node:
+ node_prop['om_numa_type'] = 'threads]'
+ node_prop['num_thread]'] = node['threads]']
+
+ nodes.append(node_prop)
+ guest_epa_prop['node'] = nodes
+
+ self.guest_epa = guest_epa_prop
+
self.remove_ignored_fields(vdu_dic)
+
+ for cp in self.ext_cp:
+ cp_name = cp[self.NAME].replace('/', '_')
+ self.conn_point_to_conection_node[cp[self.NAME]] = cp_name
+
+
if len(vdu_dic):
self.log.warn(_("{0}, Did not process the following in "
"VDU: {1}").
@@ -151,6 +276,7 @@
# Create a unique name incase multiple VNFs use same
# name for the vdu
return "{}_{}".format(vnf_name, self.name)
+ #return self.name
def generate_tosca_type(self, tosca):
self.log.debug(_("{0} Generate tosa types").
@@ -218,14 +344,35 @@
node = {}
node[self.TYPE] = self.T_VDU1
+ node[self.CAPABILITIES] = {}
- if self.HOST in self.props:
- node[self.CAPABILITIES] = {
- self.HOST: {self.PROPERTIES: self.props.pop(self.HOST)}
- }
+ if self.NFV_COMPUTE in self.props:
+ node[self.CAPABILITIES][self.NFV_COMPUTE] = {self.PROPERTIES: self.props.pop(self.NFV_COMPUTE)}
else:
self.log.warn(_("{0}, Does not have host requirements defined").
format(self))
+ if self.host_epa:
+ node[self.CAPABILITIES][self.HOST_EPA] = {
+ self.PROPERTIES: self.host_epa
+ }
+ if self.vswitch_epa:
+ node[self.CAPABILITIES][self.VSWITCH_EPA] = {
+ self.PROPERTIES: self.vswitch_epa
+ }
+ if self.hypervisor_epa:
+ node[self.CAPABILITIES][self.HYPERVISOR_EPA] = {
+ self.PROPERTIES: self.hypervisor_epa
+ }
+ if self.guest_epa:
+ node[self.CAPABILITIES]['numa_extension'] = {
+ self.PROPERTIES: self.guest_epa
+ }
+ if len(self.pinning_epa_prop) > 0:
+ if node[self.CAPABILITIES][self.NFV_COMPUTE] and node[self.CAPABILITIES][self.NFV_COMPUTE][self.PROPERTIES]:
+ node[self.CAPABILITIES][self.NFV_COMPUTE][self.PROPERTIES]['cpu_allocation'] = self.pinning_epa_prop
+ if self.mem_page_guest_epa:
+ if node[self.CAPABILITIES][self.NFV_COMPUTE] and node[self.CAPABILITIES][self.NFV_COMPUTE][self.PROPERTIES]:
+ node[self.CAPABILITIES][self.NFV_COMPUTE][self.PROPERTIES]['mem_page_size'] = self.mem_page_guest_epa
if self.IMAGE in self.props:
img_name = "{}_{}_vm_image".format(vnf_name, self.name)
@@ -241,10 +388,22 @@
node[self.INTERFACES] = {'Standard': {
'create': img_name
}}
-
# Add cloud init script if available
if self.CLOUD_INIT_FILE in self.props:
+ cloud_name = "{}_{}_cloud_init".format(vnf_name, self.name)
self.cloud_init_file = self.props[self.CLOUD_INIT_FILE]
+ cloud_init_file = "../{}/{}".format(self.CLOUD_INIT_DIR, self.props.pop(self.CLOUD_INIT_FILE))
+ if self.ARTIFACTS in node:
+ node[self.ARTIFACTS][cloud_name] = {
+ self.FILE: cloud_init_file,
+ self.TYPE: self.T_ARTF_CLOUD_INIT,
+ }
+ else:
+ node[self.ARTIFACTS] = {
+ cloud_name: {
+ self.FILE: cloud_init_file,
+ self.TYPE: self.T_ARTF_CLOUD_INIT,
+ }}
# Remove
self.props.pop(self.ID)
@@ -269,6 +428,7 @@
cpt[self.PROPERTIES] = cp
cp_name = cp[self.NAME].replace('/', '_')
+ self.cp_name_to_cp_node[cp[self.NAME]] = cp_name
self.log.debug(_("{0}, CP node {1}: {2}").
format(self, cp_name, cpt))
@@ -296,7 +456,5 @@
})
self.log.debug(_("Supporting files for {} : {}").format(self, files))
- if not len(files):
- shutil.rmtree(out_dir)
return files
diff --git a/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py b/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py
index 7449c5a..ec21e3c 100644
--- a/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py
+++ b/common/python/rift/mano/yang_translator/rwmano/yang/yang_vnfd.py
@@ -33,6 +33,7 @@
OTHER_KEYS = (MGMT_INTF, HTTP_EP, MON_PARAM) = \
('mgmt_interface', 'http_endpoint', 'monitoring_param')
+ vnf_prefix_type = 'tosca.nodes.nfv.riftio.'
def __init__(self,
@@ -49,6 +50,13 @@
self.mgmt_intf = {}
self.mon_param = []
self.http_ep = []
+ self.vnf_configuration = None
+ self.monitor_param = {}
+ self.monitor_param_1 = {}
+ self.vnf_type = None
+ self.tosca = None
+ self.script_files = []
+ self.service_function_type = None
def handle_yang(self):
self.log.debug(_("Process VNFD desc {0}: {1}").format(self.name,
@@ -56,28 +64,45 @@
def process_vnf_config(conf):
vnf_conf = {}
- if self.CONFIG_ATTR in conf:
- for key, value in conf.pop(self.CONFIG_ATTR).items():
- vnf_conf[key] = value
+ config = {}
- if self.CONFIG_TMPL in conf:
- vnf_conf[self.CONFIG_TMPL] = conf.pop(self.CONFIG_TMPL)
+ init_primitive_config = {}
+ if 'config_template' in conf:
+ config['config_template'] = conf['config_template']
+ if 'config_attributes' in conf:
+ if 'config_delay' in conf['config_attributes']:
+ config['config_delay'] = conf['config_attributes']['config_delay']
+ if 'config_priority' in conf['config_attributes']:
+ config['config_priority'] = conf['config_attributes']['config_priority']
+ if 'config_type' in conf:
+ config['config_type'] = conf['config_type']
+ if 'script' in conf:
+ config['config_details'] = conf['script']
+ for conf_type in self.CONFIG_TYPES:
+ if conf_type in conf:
+ config['config_type'] = conf_type
+ if len(config) > 0:
+ vnf_conf['config'] = config
- def copy_config_details(conf_type, conf_details):
- vnf_conf[self.CONFIG_TYPE] = conf_type
- vnf_conf[self.CONFIG_DETAILS] = conf_details
+ if 'initial_config_primitive' in conf:
+ init_config_prims = []
+ for init_conf_prim in conf['initial_config_primitive']:
+ init_conf = {}
+ if 'name' in init_conf_prim:
+ init_conf['name'] = init_conf_prim['name']
+ if 'seq' in init_conf_prim:
+ init_conf['seq'] = init_conf_prim['seq']
+ if 'user_defined_script' in init_conf_prim:
+ init_conf['user_defined_script'] = init_conf_prim['user_defined_script']
+ self.script_files.append(init_conf_prim['user_defined_script'])
+ if 'parameter' in init_conf_prim:
+ init_conf['parameter'] = []
+ for parameter in init_conf_prim['parameter']:
+ init_conf['parameter'].append({parameter['name']: parameter['value']})
+ init_config_prims.append(init_conf)
+ vnf_conf['initial_config_primitive'] = init_config_prims
- for key in self.CONFIG_TYPES:
- if key in conf:
- copy_config_details(key, conf.pop(key))
- break
-
- if len(conf):
- self.log.warn(_("{0}, Did not process all in VNF "
- "configuration {1}").
- format(self, conf))
- self.log.debug(_("{0}, vnf config: {1}").format(self, vnf_conf))
- self.props[self.VNF_CONFIG] = vnf_conf
+ self.vnf_configuration = vnf_conf
def process_mgmt_intf(intf):
if len(self.mgmt_intf) > 0:
@@ -117,7 +142,8 @@
http_ep = {'protocol': 'http'} # Required for TOSCA
http_ep[self.PATH] = ep.pop(self.PATH)
http_ep[self.PORT] = ep.pop(self.PORT)
- http_ep[self.POLL_INTVL] = ep.pop(self.POLL_INTVL_SECS)
+ if self.POLL_INTVL in http_ep:
+ http_ep[self.POLL_INTVL] = ep.pop(self.POLL_INTVL_SECS)
if len(ep):
self.log.warn(_("{0}, Did not process the following for "
"http ep {1}").format(self, ep))
@@ -130,16 +156,34 @@
fields = [self.NAME, self.ID, 'value_type', 'units', 'group_tag',
'json_query_method', 'http_endpoint_ref', 'widget_type',
self.DESC]
- for key in fields:
- if key in param:
- monp[key] = param.pop(key)
+ mon_param = {}
+ ui_param = {}
+ if 'name' in param:
+ mon_param['name'] = param['name']
+ if 'description' in param:
+ mon_param['description'] = param['description']
+ if 'polling_interval' in param:
+ mon_param['polling_interval'] = param['polling_interval']
+ if 'http_endpoint_ref' in param:
+ mon_param['url_path'] = param['http_endpoint_ref']
+ if 'json_query_method' in param:
+ mon_param['json_query_method'] = param['json_query_method'].lower()
+ if 'group_tag' in param:
+ ui_param['group_tag'] = param['group_tag']
+ if 'widget_type' in param:
+ ui_param['widget_type'] = param['widget_type'].lower()
+ if 'units' in param:
+ ui_param['units'] = param['units']
+ mon_param['ui_data'] = ui_param
+
+ self.mon_param.append(mon_param)
if len(param):
self.log.warn(_("{0}, Did not process the following for "
"monitporing-param {1}").
format(self, param))
self.log.debug(_("{0}, Monitoring param: {1}").format(self, monp))
- self.mon_param.append(monp)
+ #self.mon_param.append(monp)
def process_cp(cps):
for cp_dic in cps:
@@ -154,13 +198,15 @@
"connection-point {1}: {2}").
format(self, name, cp_dic))
+ def process_service_type(dic):
+ self.service_function_type = dic['service_function_type']
+
ENDPOINTS_MAP = {
self.MGMT_INTF: process_mgmt_intf,
self.HTTP_EP: process_http_ep,
self.MON_PARAM: process_mon_param,
'connection_point': process_cp
}
-
dic = deepcopy(self.yang)
try:
for key in self.REQUIRED_FIELDS:
@@ -176,14 +222,15 @@
self.VDU, vdu_dic)
vdu.process_vdu()
self.vdus.append(vdu)
-
for key in ENDPOINTS_MAP.keys():
if key in dic:
ENDPOINTS_MAP[key](dic.pop(key))
-
if self.VNF_CONFIG in dic:
process_vnf_config(dic.pop(self.VNF_CONFIG))
+ if 'service_function_type' in dic:
+ process_service_type(dic)
+
self.remove_ignored_fields(dic)
if len(dic):
self.log.warn(_("{0}, Did not process the following for "
@@ -202,135 +249,54 @@
if cp:
vdu.set_vld(cp_name, vld_name)
break
+ def _generate_vnf_type(self, tosca):
+ name = self.name.replace("_","")
+ name = name.split('_', 1)[0]
+ self.vnf_type = "{0}{1}{2}".format(self.vnf_prefix_type, name, 'VNF')
+ if self.NODE_TYPES not in tosca and self.vnf_type:
+ tosca[self.NODE_TYPES] = {}
+ tosca[self.NODE_TYPES][self.vnf_type] = {
+ self.DERIVED_FROM : self.T_VNF1
+ }
- def generate_tosca_type(self, tosca):
- self.log.debug(_("{0} Generate tosa types").
- format(self))
+ def generate_tosca_template(self, tosca):
+ self.tosca = tosca
+ tosca['tosca_definitions_version'] = 'tosca_simple_profile_for_nfv_1_0'
+ tosca[self.IMPORT] = []
+ tosca[self.IMPORT].append("riftiotypes.yaml")
+ tosca[self.DESC] = self.props[self.DESC]
+ tosca[self.METADATA] = {
+ 'ID': self.name,
+ self.VENDOR: self.props[self.VENDOR],
+ self.VERSION: self.props[self.VERSION],
+ }
+ if self.name:
+ self._generate_vnf_type(tosca);
+
+
+ tosca[self.TOPOLOGY_TMPL] = {}
+ tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL] = {}
+ tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING] = {}
+ tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING]['node_type'] = self.vnf_type
for vdu in self.vdus:
- tosca = vdu.generate_tosca_type(tosca)
-
- # Add data_types
- if self.T_VNF_CONFIG not in tosca[self.DATA_TYPES]:
- tosca[self.DATA_TYPES][self.T_VNF_CONFIG] = {
- self.PROPERTIES:
- {self.CONFIG_TYPE:
- {self.TYPE: self.STRING},
- 'config_delay':
- {self.TYPE: self.INTEGER,
- self.DEFAULT: 0,
- self.REQUIRED: self.NO,
- self.CONSTRAINTS:
- [{'greater_or_equal': 0}]},
- 'config_priority':
- {self.TYPE: self.INTEGER,
- self.CONSTRAINTS:
- [{'greater_than': 0}]},
- self.CONFIG_DETAILS:
- {self.TYPE: self.MAP},
- self.CONFIG_TMPL:
- {self.TYPE: self.STRING,
- self.REQUIRED: self.NO},
- }
- }
-
- # Add capability types
- if self.CAPABILITY_TYPES not in tosca:
- tosca[self.CAPABILITY_TYPES] = {}
- if self.T_HTTP_EP not in tosca[self.CAPABILITY_TYPES]:
- tosca[self.CAPABILITY_TYPES][self.T_HTTP_EP] = {
- self.DERIVED_FROM: 'tosca.capabilities.Endpoint',
- self.PROPERTIES: {
- 'polling_interval':
- {self.TYPE: self.INTEGER},
- 'path':
- {self.TYPE: self.STRING},
- },
- }
-
- if self.T_MGMT_INTF not in tosca[self.CAPABILITY_TYPES]:
- tosca[self.CAPABILITY_TYPES][self.T_MGMT_INTF] = {
- self.DERIVED_FROM: 'tosca.capabilities.Endpoint',
- self.PROPERTIES: {
- self.DASHBOARD_PARAMS:
- {self.TYPE: self.MAP},
- self.VDU:
- {self.TYPE: self.STRING},
- },
- }
-
- if self.T_MON_PARAM not in tosca[self.CAPABILITY_TYPES]:
- tosca[self.CAPABILITY_TYPES][self.T_MON_PARAM] = {
- self.DERIVED_FROM: 'tosca.capabilities.nfv.Metric',
- self.PROPERTIES: {
- 'id':
- {self.TYPE: self.INTEGER},
- 'name':
- {self.TYPE: self.STRING},
- 'value_type':
- {self.TYPE: self.STRING,
- self.DEFAULT: 'INT'},
- 'group_tag':
- {self.TYPE: self.STRING,
- self.DEFAULT: 'Group1'},
- 'units':
- {self.TYPE: self.STRING},
- 'description':
- {self.TYPE: self.STRING},
- 'json_query_method':
- {self.TYPE: self.STRING,
- self.DEFAULT: 'NAMEKEY'},
- 'http_endpoint_ref':
- {self.TYPE: self.STRING},
- 'widget_type':
- {self.TYPE: self.STRING,
- self.DEFAULT: 'COUNTER'},
- }
- }
-
- # Define the VNF type
- if self.T_VNF1 not in tosca[self.NODE_TYPES]:
- tosca[self.NODE_TYPES][self.T_VNF1] = {
- self.DERIVED_FROM: 'tosca.nodes.nfv.VNF',
- self.PROPERTIES: {
- 'vnf_configuration':
- {self.TYPE: self.T_VNF_CONFIG},
- 'port':
- {self.TYPE: self.INTEGER,
- self.CONSTRAINTS:
- [{'in_range': '[1, 65535]'}]},
- self.START_BY_DFLT:
- {self.TYPE: self.BOOL,
- self.DEFAULT: self.TRUE},
- },
- self.CAPABILITIES: {
- 'mgmt_interface':
- {self.TYPE: self.T_MGMT_INTF},
- 'http_endpoint':
- {self.TYPE: self.T_HTTP_EP},
- 'monitoring_param_0':
- {self.TYPE: self.T_MON_PARAM},
- 'monitoring_param_1':
- {self.TYPE: self.T_MON_PARAM},
- },
- self.REQUIREMENTS: [
- {'vdus':
- {self.TYPE: 'tosca.capabilities.nfv.VirtualLinkable',
- self.RELATIONSHIP:
- 'tosca.relationships.nfv.VirtualLinksTo',
- self.NODE: self.T_VDU1,
- self.OCCURENCES: '[1, UNBOUND]'}}
- ],
- }
-
- return tosca
-
- def generate_vnf_template(self, tosca, index):
- self.log.debug(_("{0}, Generate tosca template for VNF {1}").
- format(self, index, tosca))
-
- for vdu in self.vdus:
- tosca = vdu.generate_vdu_template(tosca, self.name)
+ vdu.generate_vdu_template(tosca, self.name)
+ if 'vdu' in self.mgmt_intf and self.mgmt_intf['vdu'] == vdu.get_name(self.name): #TEST
+ mgmt_interface = {}
+ mgmt_interface[self.PROPERTIES] = self.mgmt_intf
+ self.mgmt_intf.pop('vdu')
+ caps = []
+ tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vdu.get_name(self.name)][self.CAPABILITIES]['mgmt_interface'] = mgmt_interface #TEST
+ if len(self.mon_param) > 0:
+ mon_param = {}
+ mon_param = {}
+ mon_param['properties'] = self.mon_param[0]
+ tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vdu.get_name(self.name)][self.CAPABILITIES]['monitoring_param'] = mon_param #TEST
+ if len(self.mon_param) == 2:
+ mon_param = {}
+ mon_param = {}
+ mon_param['properties'] = self.mon_param[1]
+ tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][vdu.get_name(self.name)][self.CAPABILITIES]['monitoring_param_1'] = mon_param
node = {}
node[self.TYPE] = self.T_VNF1
@@ -339,7 +305,9 @@
self.props.pop(self.DESC)
# Update index to the member-vnf-index
- self.props[self.ID] = index
+
+ # For now I am putting index as 1. This needs to be revisted
+ self.props[self.ID] = 1
node[self.PROPERTIES] = self.props
caps = {}
@@ -378,16 +346,88 @@
self.log.debug(_("{0}, VNF node: {1}").format(self, node))
- tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][self.name] = node
+ #tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][self.name] = node
+ self.get_vnf_configuration_policy(tosca)
return tosca
- def get_supporting_files(self):
- files = []
+ def generate_vld_link(self, virtualLink, conn_point):
+ if self.REQUIREMENTS not in self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING]:
+ self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING] = {}
+ self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING]['node_type'] = self.vnf_type
+ #self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING]['node_type'] = []
+ #self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING]['node_type'].\
+ #append(['node_type', self.vnf_type])
+ self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.REQUIREMENTS] = []
for vdu in self.vdus:
- f = vdu.get_supporting_files()
- if f and len(f):
- files.extend(f)
+ if conn_point in vdu.cp_name_to_cp_node:
+ conn_point_node_name = vdu.cp_name_to_cp_node[conn_point]
+ self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.REQUIREMENTS].\
+ append({virtualLink : "[{0}, {1}]".format(conn_point_node_name, "virtualLink")})
+
+ if self.REQUIREMENTS not in self.tosca[self.NODE_TYPES][self.vnf_type]:
+ self.tosca[self.NODE_TYPES][self.vnf_type][self.REQUIREMENTS] = []
+ self.tosca[self.NODE_TYPES][self.vnf_type][self.REQUIREMENTS].append({virtualLink : {
+ "type": "tosca.nodes.nfv.VL"}})
+ def generate_forwarder_sub_mapping(self, sub_link):
+ if self.CAPABILITIES not in self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING]:
+ self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.CAPABILITIES] = {}
+ self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.CAPABILITIES]
+
+ self.tosca[self.TOPOLOGY_TMPL][self.SUBSTITUTION_MAPPING][self.CAPABILITIES][sub_link[1]] = \
+ "[{}, forwarder]".format(sub_link[2])
+
+ def generate_sfc_link(self, sfs_conn_point_name):
+ for vdu in self.vdus:
+ if sfs_conn_point_name in vdu.cp_name_to_cp_node:
+ conn_point_node_name = vdu.cp_name_to_cp_node[sfs_conn_point_name]
+ if conn_point_node_name in self.tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL]:
+ if self.CAPABILITIES not in self.tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL]:
+ self.tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][conn_point_node_name][self.CAPABILITIES] = {}
+ self.tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][conn_point_node_name][self.CAPABILITIES]['sfc'] = {self.PROPERTIES: {}}
+ self.tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][conn_point_node_name] \
+ [self.CAPABILITIES]['sfc'][self.PROPERTIES]['sfc_type'] = 'sf'
+
+ if self.service_function_type:
+ self.tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL][conn_point_node_name] \
+ [self.CAPABILITIES]['sfc'][self.PROPERTIES]['sf_type'] = self.service_function_type
+
+ def generate_tosca(self):
+ tosca = {}
+ return tosca
+
+ def get_vnf_configuration_policy(self, tosca):
+ if self.vnf_configuration:
+ if self.POLICIES in tosca:
+ tosca[self.TOPOLOGY_TMPL][self.POLICIES]['configuration'] ={
+ 'type' : self.T_VNF_CONFIG,
+ self.PROPERTIES: self.vnf_configuration
+ }
+ else:
+ tosca[self.TOPOLOGY_TMPL][self.POLICIES] = []
+ # This is bad hack. TOSCA Openstack does not return policies without target
+ if len(tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL]) > 0:
+ node_name = list(tosca[self.TOPOLOGY_TMPL][self.NODE_TMPL].keys())[0]
+ tosca[self.TOPOLOGY_TMPL][self.POLICIES].append({'configuration' :{
+ 'type' : self.T_VNF_CONFIG,
+ self.PROPERTIES: self.vnf_configuration,
+ self.TARGETS : "[{0}]".format(node_name)
+ }})
+
+ def get_supporting_files(self):
+ files = []
+ for file in self.script_files:
+ files.append({
+ self.TYPE: 'script',
+ self.NAME: file,
+ self.DEST: "{}/{}".format(self.SCRIPT_DIR, file),
+ })
+
+
+ for vdu in self.vdus:
+ vdu_files = vdu.get_supporting_files()
+ for vdu_file in vdu_files:
+ files.append(vdu_file)
return files
diff --git a/common/python/rift/mano/yang_translator/rwmano/yang_translator.py b/common/python/rift/mano/yang_translator/rwmano/yang_translator.py
index 907a4a0..0919494 100644
--- a/common/python/rift/mano/yang_translator/rwmano/yang_translator.py
+++ b/common/python/rift/mano/yang_translator/rwmano/yang_translator.py
@@ -48,24 +48,36 @@
self.tosca_template = ToscaTemplate(log)
self.node_translator = None
self.pkgs = packages
+ self.output_files = {}
+ self.output_files['nsd'] = []
+ self.output_files['vnfd'] = []
+
log.info(_('Initialized parameters for translation.'))
def translate(self):
if self.files:
self.get_yangs()
+ else:
+ if 'nsd' in self.yangs:
+ self.output_files['nsd'].append(self.yangs['nsd'][0]['short_name'])
+ if 'vnfd' in self.yangs:
+ for yang_vnfd in self.yangs['vnfd']:
+ self.output_files['vnfd'].append(yang_vnfd['short_name'])
self.node_translator = TranslateDescriptors(self.log,
self.yangs,
- self.tosca_template)
-
+ self.tosca_template,
+ self.output_files['vnfd'])
self.tosca_template.resources = self.node_translator.translate()
+
return self.tosca_template.output_to_tosca()
def get_yangs(self):
'''Get the descriptors and convert to yang instances'''
for filename in self.files:
self.log.debug(_("Load file {0}").format(filename))
+
# Only one descriptor per file
if tarfile.is_tarfile(filename):
tar = open(filename, "r+b")
@@ -78,36 +90,70 @@
self.yangs[TranslateDescriptors.NSD] = []
self.yangs[TranslateDescriptors.NSD]. \
append(pkg.descriptor_msg.as_dict())
+ if 'name' in pkg.descriptor_msg.as_dict() is not None:
+ self.output_files['nsd'].append(pkg.descriptor_msg.as_dict()['name'])
+ else:
+ raise ValidationError(message="NSD Descriptor name attribute is not populated ")
elif desc_type == TranslateDescriptors.VNFD:
if TranslateDescriptors.VNFD not in self.yangs:
self.yangs[TranslateDescriptors.VNFD] = []
self.yangs[TranslateDescriptors.VNFD]. \
append(pkg.descriptor_msg.as_dict())
+ if 'name' in pkg.descriptor_msg.as_dict() is not None:
+ self.output_files['vnfd'].append(pkg.descriptor_msg.as_dict()['name'])
+ else:
+ raise ValidationError(message="VNFD Descriptor name attribute is not populated ")
else:
raise ValidationError("Unknown descriptor type: {}".
format(desc_type))
- def _create_csar_files(self, output_dir, name, tmpl,
+ def _create_csar_files(self, output_dir, tmpl_out,
archive=False):
- if ToscaTemplate.TOSCA not in tmpl:
- self.log.error(_("Did not find TOSCA template for {0}").
- format(name))
- return
-
+ '''
+ for tmpl in tmpl_out:
+ if ToscaTemplate.TOSCA not in tmpl:
+ self.log.error(_("Did not find TOSCA template for {0}").
+ format(tmpl))
+ return
+ '''
# Create sub for each NS template
- subdir = os.path.join(output_dir, name)
+ sub_folder_name = None
+ if self.files:
+ if len(self.output_files['nsd']) > 0:
+ if len(self.output_files['nsd']) == 1:
+ sub_folder_name = self.output_files['nsd'][0]
+ else:
+ raise ValidationError(message="Multiple NSD Descriptor uploaded ")
+ elif len(self.output_files['vnfd']) > 0:
+ if len(self.output_files['vnfd']) == 1:
+ sub_folder_name = self.output_files['vnfd'][0]
+ else:
+ raise ValidationError(message="Multiple VNFDs Descriptors uploaded without NSD")
+ else:
+ raise ValidationError(message="No NSD or VNFD uploaded")
+ else:
+ if 'nsd' in self.yangs:
+ sub_folder_name = self.yangs['nsd'][0]['short_name']
+ elif 'vnfd' in self.yangs:
+ sub_folder_name = self.yangs['vnfd'][0]['short_name']
+
+
+ subdir = os.path.join(output_dir, sub_folder_name)
if os.path.exists(subdir):
shutil.rmtree(subdir)
os.makedirs(subdir)
-
+ riftio_src_file = "{0}{1}".format(os.getenv('RIFT_INSTALL'), "/usr/rift/mano/common/riftiotypes.yaml")
# Create the definitions dir
def_dir = os.path.join(subdir, 'Definitions')
os.makedirs(def_dir)
- entry_file = os.path.join(def_dir, name+'.yaml')
- self.log.debug(_("Writing file {0}").
- format(entry_file))
- with open(entry_file, 'w+') as f:
- f.write(tmpl[ToscaTemplate.TOSCA])
+ shutil.copy2(riftio_src_file, def_dir + "/riftiotypes.yaml")
+ for tmpl_key in tmpl_out:
+ tmpl = tmpl_out[tmpl_key]
+ entry_file = os.path.join(def_dir, tmpl_key+'.yaml')
+ self.log.debug(_("Writing file {0}").
+ format(entry_file))
+ with open(entry_file, 'w+') as f:
+ f.write(tmpl[ToscaTemplate.TOSCA])
# Create the Tosca meta
meta_dir = os.path.join(subdir, 'TOSCA-Metadata')
@@ -116,7 +162,7 @@
CSAR-Version: 1.1
Created-By: RIFT.io
Entry-Definitions: Definitions/'''
- meta_data = "{}{}".format(meta, name+'.yaml')
+ meta_data = "{}{}".format(meta, sub_folder_name+'.yaml')
meta_file = os.path.join(meta_dir, 'TOSCA.meta')
self.log.debug(_("Writing file {0}:\n{1}").
format(meta_file, meta_data))
@@ -124,53 +170,55 @@
f.write(meta_data)
# Copy other supporting files
- if ToscaTemplate.FILES in tmpl:
- for f in tmpl[ToscaTemplate.FILES]:
- self.log.debug(_("Copy supporting file {0}").format(f))
+ for key in tmpl_out:
+ tmpl = tmpl_out[key]
+ if ToscaTemplate.FILES in tmpl:
+ for f in tmpl[ToscaTemplate.FILES]:
+ self.log.debug(_("Copy supporting file {0}").format(f))
- # Search in source packages
- if len(self.pkgs):
- for pkg in self.pkgs:
- # TODO(pjoseph): Need to add support for other file types
- fname = f[ToscaResource.NAME]
- dest_path = os.path.join(subdir, f[ToscaResource.DEST])
- ftype = f[ToscaResource.TYPE]
+ # Search in source packages
+ if len(self.pkgs):
+ for pkg in self.pkgs:
+ # TODO(pjoseph): Need to add support for other file types
+ fname = f[ToscaResource.NAME]
+ dest_path = os.path.join(subdir, f[ToscaResource.DEST])
+ ftype = f[ToscaResource.TYPE]
- if ftype == 'image':
- image_file_map = rift.package.image.get_package_image_files(pkg)
+ if ftype == 'image':
+ image_file_map = rift.package.image.get_package_image_files(pkg)
- if fname in image_file_map:
- self.log.debug(_("Extracting image {0} to {1}").
- format(fname, dest_path))
- pkg.extract_file(image_file_map[fname],
- dest_path)
- break
+ if fname in image_file_map:
+ self.log.debug(_("Extracting image {0} to {1}").
+ format(fname, dest_path))
+ pkg.extract_file(image_file_map[fname],
+ dest_path)
+ break
- elif ftype == 'script':
- script_file_map = \
- rift.package.script.PackageScriptExtractor.package_script_files(pkg)
- if fname in script_file_map:
- self.log.debug(_("Extracting script {0} to {1}").
- format(fname, dest_path))
- pkg.extract_file(script_file_map[fname],
- dest_path)
- break
+ elif ftype == 'script':
+ script_file_map = \
+ rift.package.script.PackageScriptExtractor.package_script_files(pkg)
+ if fname in script_file_map:
+ self.log.debug(_("Extracting script {0} to {1}").
+ format(fname, dest_path))
+ pkg.extract_file(script_file_map[fname],
+ dest_path)
+ break
- elif ftype == 'cloud_init':
- script_file_map = \
- rift.package.cloud_init.PackageCloudInitExtractor.package_script_files(pkg)
- if fname in script_file_map:
- self.log.debug(_("Extracting script {0} to {1}").
- format(fname, dest_path))
- pkg.extract_file(script_file_map[fname],
- dest_path)
- break
+ elif ftype == 'cloud_init':
+ script_file_map = \
+ rift.package.cloud_init.PackageCloudInitExtractor.package_script_files(pkg)
+ if fname in script_file_map:
+ self.log.debug(_("Extracting script {0} to {1}").
+ format(fname, dest_path))
+ pkg.extract_file(script_file_map[fname],
+ dest_path)
+ break
- else:
- self.log.warn(_("Unknown file type {0}: {1}").
- format(ftype, f))
+ else:
+ self.log.warn(_("Unknown file type {0}: {1}").
+ format(ftype, f))
- #TODO(pjoseph): Search in other locations
+ #TODO(pjoseph): Search in other locations
# Create the ZIP archive
if archive:
@@ -178,7 +226,7 @@
os.chdir(subdir)
try:
- zip_file = name + '.zip'
+ zip_file = key + '.zip'
zip_path = os.path.join(output_dir, zip_file)
self.log.debug(_("Creating zip file {0}").format(zip_path))
zip_cmd = "zip -r {}.partial ."
@@ -207,14 +255,12 @@
archive=False,):
if output:
zip_files = []
- for key in output.keys():
- if output_dir:
- zf = self._create_csar_files(output_dir,
- key,
- output[key],
- archive=archive,)
- zip_files.append(zf)
- else:
- print(_("TOSCA Template {0}:\n{1}").
- format(key, output[key]))
+ #for key in output.keys():
+ if output_dir:
+ zf = self._create_csar_files(output_dir,
+ output,
+ archive=archive,)
+ zip_files.append(zf)
+ else:
+ print(_("There is an issue with TOSCA Template"))
return zip_files
diff --git a/models/plugins/yang/mano-types.yang b/models/plugins/yang/mano-types.yang
index 1013595..aad8972 100644
--- a/models/plugins/yang/mano-types.yang
+++ b/models/plugins/yang/mano-types.yang
@@ -1072,7 +1072,7 @@
type string;
}
- leaf polling_interval_secs {
+ leaf polling-interval-secs {
description "The HTTP polling interval in seconds";
type uint8;
default 2;
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py
index 7fa6130..ff6a373 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py
@@ -326,11 +326,6 @@
if format_ != "yaml":
log.warn("Only yaml format supported for TOSCA export")
- if desc_type != "nsd":
- raise tornado.web.HTTPError(
- 400,
- "NSD need to passed to generate TOSCA: {}".format(desc_type))
-
def get_pkg_from_store(id_, type_):
package = None
# Attempt to get the package from the package store
@@ -345,27 +340,38 @@
return package
- pkg = tosca.ExportTosca()
+ if desc_type == "nsd":
+ pkg = tosca.ExportTosca()
- # Add NSD and related descriptors for exporting
- nsd_id = pkg.add_nsd(desc_msg, get_pkg_from_store(desc_id, "nsd"))
+ # Add NSD and related descriptors for exporting
+ nsd_id = pkg.add_nsd(desc_msg, get_pkg_from_store(desc_id, "nsd"))
- catalog = self.catalog_map["vnfd"]
- for const_vnfd in desc_msg.constituent_vnfd:
- vnfd_id = const_vnfd.vnfd_id_ref
- if vnfd_id in catalog:
- pkg.add_vnfd(nsd_id,
- catalog[vnfd_id],
- get_pkg_from_store(vnfd_id, "vnfd"))
- else:
- raise tornado.web.HTTPError(
- 400,
- "Unknown VNFD descriptor {} for NSD {}".
- format(vnfd_id, nsd_id))
+ catalog = self.catalog_map["vnfd"]
+ for const_vnfd in desc_msg.constituent_vnfd:
+ vnfd_id = const_vnfd.vnfd_id_ref
+ if vnfd_id in catalog:
+ pkg.add_vnfd(nsd_id,
+ catalog[vnfd_id],
+ get_pkg_from_store(vnfd_id, "vnfd"))
+ else:
+ raise tornado.web.HTTPError(
+ 400,
+ "Unknown VNFD descriptor {} for NSD {}".
+ format(vnfd_id, nsd_id))
- # Create the archive.
- pkg.create_archive(transaction_id,
- dest=self.application.export_dir)
+ # Create the archive.
+ pkg.create_archive(transaction_id,
+ dest=self.application.export_dir)
+ if desc_type == "vnfd":
+ pkg = tosca.ExportTosca()
+ vnfd_id = desc_msg.id
+ pkg.add_single_vnfd(vnfd_id,
+ desc_msg,
+ get_pkg_from_store(vnfd_id, "vnfd"))
+
+ # Create the archive.
+ pkg.create_archive(transaction_id,
+ dest=self.application.export_dir)
class ExportStateHandler(state.StateHandler):
diff --git a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tosca.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tosca.py
index 8ccc899..d61e47e 100644
--- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tosca.py
+++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tosca.py
@@ -61,6 +61,7 @@
self.log = log
self.nsds = {}
self.csars = list()
+ self.vnfds = {}
def add_image(self, nsd_id, image, chksum=None):
if image.name not in self.images:
@@ -73,6 +74,14 @@
if pkg:
self.nsds[nsd_id]['pkgs'].append(pkg)
+ def add_single_vnfd(self, vnfd_id, vnfd, pkg=None):
+ if vnfd is not None:
+ self.vnfds['vnfds'] = []
+ self.vnfds['pkgs'] = []
+ self.vnfds['vnfds'].append(vnfd)
+ if pkg:
+ self.vnfds['pkgs'].append(pkg)
+
def add_vnfd(self, nsd_id, vnfd, pkg=None):
if not 'vnfds' in self.nsds[nsd_id]:
self.nsds[nsd_id]['vnfds'] = []
@@ -112,8 +121,25 @@
archive=True))
self.log.debug("Created CSAR archive {}".format(self.csars[-1]))
+ def create_vnfd_csar(self, dest=None):
+ if dest is None:
+ dest = tempfile.mkdtemp()
+ yangs = {}
+ yangs['vnfd'] = []
+ for vnfd in self.vnfds['vnfds']:
+ yangs['vnfd'].append(vnfd.as_dict())
+ translator = YangTranslator(self.log,
+ yangs=yangs,
+ packages=self.vnfds['pkgs'])
+ output = translator.translate()
+ self.csars.extend(translator.write_output(output,
+ output_dir=dest,
+ archive=True))
+ self.log.debug("Created CSAR archive {}".format(self.csars[-1]))
+
+
def create_archive(self, archive_name, dest=None):
- if not len(self.nsds):
+ if not len(self.nsds) and len(self.vnfds) == 0:
self.log.error("Did not find any NSDs to export")
return
@@ -127,13 +153,16 @@
try:
# Convert each NSD to a TOSCA template
- for nsd_id in self.nsds:
- # Not passing the dest dir to prevent clash in case
- # multiple export of the same desc happens
- self.create_csar(nsd_id)
+ if len(self.nsds) > 0:
+ for nsd_id in self.nsds:
+ # Not passing the dest dir to prevent clash in case
+ # multiple export of the same desc happens
+ self.create_csar(nsd_id)
+ elif len(self.vnfds) > 0:
+ self.create_vnfd_csar()
except Exception as e:
- msg = "Exception converting NSD {}: {}".format(nsd_id, e)
+ msg = "Exception converting NSD/VNFD {}".format(e)
self.log.exception(e)
raise YangTranslateNsdError(msg)