From: Hashir Mohammed Date: Wed, 1 Mar 2017 12:42:47 +0000 (-0500) Subject: * YANG to TOSCA translator X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F31%2F1331%2F1;p=osm%2FSO.git * YANG to TOSCA translator * Bug fixes - TOSCA to YANG Signed-off-by: Hashir Mohammed --- diff --git a/common/python/CMakeLists.txt b/common/python/CMakeLists.txt index 22018c39..50ed1de7 100644 --- a/common/python/CMakeLists.txt +++ b/common/python/CMakeLists.txt @@ -112,6 +112,10 @@ rift_python_install_tree( 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 @@ -167,6 +171,20 @@ set(TRANSLATOR_SCRIPTS ${CMAKE_CURRENT_SOURCE_DIR}/rift/mano/tosca_translator/tosca-translator ${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 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 00000000..6798e2ae --- /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 7bc0bf3b..79384857 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 @@ -47,6 +47,16 @@ class ToscaCompute(ManoResource): '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, nodetemplate, @@ -62,6 +72,7 @@ class ToscaCompute(ManoResource): self._id = self.name self._monitor_param = [] self._mgmt_interface = {} + self._http_endpoint = None @property def image(self): @@ -207,11 +218,11 @@ class ToscaCompute(ManoResource): if 'type' in specs: hypervisor_epa['type'] = specs['type'].upper() if 'version' in specs: - hypervisor_epa['version'] = specs['version'] + hypervisor_epa['version'] = str(specs['version']) return hypervisor_epa - def get_guest_epa(specs): + def get_guest_epa(specs, nfv_comput_specs): guest_epa = {} guest_epa['numa-node-policy'] = {} guest_epa['numa-node-policy']['node'] = [] @@ -230,6 +241,11 @@ class ToscaCompute(ManoResource): 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: @@ -245,6 +261,16 @@ class ToscaCompute(ManoResource): 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() @@ -261,13 +287,23 @@ class ToscaCompute(ManoResource): 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']) + 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: @@ -284,9 +320,11 @@ class ToscaCompute(ManoResource): prefix, type_ = value.rsplit('.', 1) if type_ == 'QCOW2': details['type'] = 'qcow2' + 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 @@ -325,6 +363,7 @@ class ToscaCompute(ManoResource): 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: @@ -389,6 +428,8 @@ class ToscaCompute(ManoResource): 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_network_network.py b/common/python/rift/mano/tosca_translator/rwmano/tosca/tosca_network_network.py index a2dd92ba..a94624de 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 @@ -49,6 +49,7 @@ class ToscaNetwork(ManoResource): 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: @@ -63,13 +64,13 @@ class ToscaNetwork(ManoResource): for mapping in substitution_mapping_list: if req_key in mapping: # link the VLD to the connection point - node = self.get_node_with_name(mapping[req_key][0], nodes) + node_vld = self.get_node_with_name(mapping[req_key][0], nodes) if node: #print() prop = {} - prop['member-vnf-index-ref'] = index_count - prop['vnfd-connection-point-ref'] = node.cp_name - prop['vnfd-id-ref'] = node.vnf._id + 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: @@ -79,10 +80,8 @@ class ToscaNetwork(ManoResource): def get_ip_profile_props(specs): ip_profile_prop = {} ip_profile_param = {} - if 'name' in specs: - ip_profile_prop['name'] = specs['name'] - elif 'description' in specs: - ip_profile_prop['name'] = specs['description'] + 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'] 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 index 0a54bcc0..f90c1874 100644 --- 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 @@ -44,12 +44,17 @@ class ToscaVnfConfiguration(ManoResource): 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"] = {} @@ -64,6 +69,20 @@ class ToscaVnfConfiguration(ManoResource): 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): @@ -86,4 +105,16 @@ class ToscaVnfConfiguration(ManoResource): tosca_props[prop.name] = {'get_param': prop.value.input_name} else: tosca_props[prop.name] = prop.value - return tosca_props \ No newline at end of file + 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 3f74336c..2d6c3e1a 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 ToscaClassImportError 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): @@ -197,6 +198,7 @@ class TranslateNodeTemplates(object): 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) @@ -214,6 +216,7 @@ class TranslateNodeTemplates(object): 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: @@ -226,10 +229,11 @@ class TranslateNodeTemplates(object): policies.append(policy.name) for req in template.substitution_mappings.requirements: vnf_type_substitution_mapping[template.substitution_mappings.node_type].append(req) - 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]}) + 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) @@ -245,11 +249,36 @@ class TranslateNodeTemplates(object): metadata=self.metadata) # Currently tosca-parser does not add the artifacts # to the node + 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 for group in self.tosca.topology_template.groups: group_type = group.type 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 00000000..a7550403 Binary files /dev/null and b/common/python/rift/mano/tosca_translator/test/data/ping_pong_csar_tosca_new_spec.zip 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 00000000..2fea0e33 --- /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: 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/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 f05933b0..7143e675 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 @@ from rift.mano.yang_translator.common.utils import _ 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 @@ class ToscaResource(object): 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'] @@ -66,17 +68,17 @@ class ToscaResource(object): 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,32 @@ class ToscaResource(object): T_SCALE_GRP, T_ARTF_QCOW2, T_INITIAL_CFG, + T_ARTF_CLOUD_INIT, + T_PLACEMENT, + T_ELAN ) = \ - ('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' ) 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 7c31df59..95f2cb26 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 @@ class ToscaTemplate(object): 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 @@ class ToscaTemplate(object): 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 @@ class ToscaTemplate(object): 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 @@ class ToscaTemplate(object): 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 @@ class ToscaTemplate(object): 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 @@ class ToscaTemplate(object): 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 f0a68665..707ab7fb 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 @@ class TranslateDescriptors(object): 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 @@ class TranslateDescriptors(object): 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) - - 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.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) + + 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 491bd86d..4e421d1f 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 @@ -49,7 +49,8 @@ class YangNsd(ToscaResource): log, name, type_, - yang): + yang, + vnfd_files): super(YangNsd, self).__init__(log, name, type_, @@ -57,10 +58,16 @@ class YangNsd(ToscaResource): 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 = {} def handle_yang(self, vnfds): self.log.debug(_("Process NSD desc {0}: {1}"). @@ -85,6 +92,7 @@ class YangNsd(ToscaResource): 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 +168,82 @@ class YangNsd(ToscaResource): 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'] + 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) dic = deepcopy(self.yang) try: @@ -177,10 +260,8 @@ class YangNsd(ToscaResource): # 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 config primitives if self.CONF_PRIM in dic: @@ -212,6 +293,10 @@ class YangNsd(ToscaResource): 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 +311,14 @@ class YangNsd(ToscaResource): 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 +373,25 @@ class YangNsd(ToscaResource): 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 +400,38 @@ class YangNsd(ToscaResource): 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) + + 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] # add the config primitives if len(self.conf_prims): @@ -361,33 +475,38 @@ class YangNsd(ToscaResource): 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) 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 7d095c1e..3786d86c 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 @@ class YangVdu(ToscaResource): '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,15 @@ class YangVdu(ToscaResource): 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 def process_vdu(self): self.log.debug(_("Process VDU desc {0}: {1}").format(self.name, @@ -88,9 +104,9 @@ class YangVdu(ToscaResource): 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 +119,110 @@ class YangVdu(ToscaResource): 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) + if len(vdu_dic): self.log.warn(_("{0}, Did not process the following in " "VDU: {1}"). @@ -151,6 +270,7 @@ class YangVdu(ToscaResource): # 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 +338,35 @@ class YangVdu(ToscaResource): 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 +382,22 @@ class YangVdu(ToscaResource): 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 +422,7 @@ class YangVdu(ToscaResource): 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 +450,5 @@ class YangVdu(ToscaResource): }) 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 9ff53e2f..1094c141 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 @@ class YangVnfd(ToscaResource): 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,12 @@ class YangVnfd(ToscaResource): 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 = [] def handle_yang(self): self.log.debug(_("Process VNFD desc {0}: {1}").format(self.name, @@ -56,28 +63,45 @@ class YangVnfd(ToscaResource): 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 - - if self.CONFIG_TMPL in conf: - vnf_conf[self.CONFIG_TMPL] = conf.pop(self.CONFIG_TMPL) - - def copy_config_details(conf_type, conf_details): - vnf_conf[self.CONFIG_TYPE] = conf_type - vnf_conf[self.CONFIG_DETAILS] = conf_details - - 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 + config = {} + + 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 + + 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 + + self.vnf_configuration = vnf_conf def process_mgmt_intf(intf): if len(self.mgmt_intf) > 0: @@ -131,16 +155,34 @@ class YangVnfd(ToscaResource): 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: @@ -161,7 +203,6 @@ class YangVnfd(ToscaResource): self.MON_PARAM: process_mon_param, 'connection_point': process_cp } - dic = deepcopy(self.yang) try: for key in self.REQUIRED_FIELDS: @@ -177,11 +218,9 @@ class YangVnfd(ToscaResource): 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)) @@ -203,135 +242,53 @@ class YangVnfd(ToscaResource): if cp: vdu.set_vld(cp_name, vld_name) break - - def generate_tosca_type(self, tosca): - self.log.debug(_("{0} Generate tosa types"). - format(self)) - - 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'}, - } + def _generate_vnf_type(self, tosca): + name = self.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 } - # 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]'}} - ], - } + 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); - return tosca - def generate_vnf_template(self, tosca, index): - self.log.debug(_("{0}, Generate tosca template for VNF {1}"). - format(self, index, 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_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 @@ -340,7 +297,9 @@ class YangVnfd(ToscaResource): 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 = {} @@ -379,16 +338,67 @@ class YangVnfd(ToscaResource): 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 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: + 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_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: - f = vdu.get_supporting_files() - if f and len(f): - files.extend(f) + 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 907a4a0e..09194943 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 @@ class YangTranslator(object): 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 @@ class YangTranslator(object): 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 @@ class YangTranslator(object): 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 @@ Entry-Definitions: Definitions/''' 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)) - - # 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 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 == '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)) - - #TODO(pjoseph): Search in other locations + 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] + + 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 + + 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 + + else: + self.log.warn(_("Unknown file type {0}: {1}"). + format(ftype, f)) + + #TODO(pjoseph): Search in other locations # Create the ZIP archive if archive: @@ -178,7 +226,7 @@ Entry-Definitions: Definitions/''' 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 @@ Entry-Definitions: Definitions/''' 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/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py index 7fa61301..ff6a3730 100644 --- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py +++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/export.py @@ -326,11 +326,6 @@ class ExportRpcHandler(mano_dts.AbstractRpcHandler): 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 @@ class ExportRpcHandler(mano_dts.AbstractRpcHandler): return package - pkg = tosca.ExportTosca() - - # 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)) - - # Create the archive. - pkg.create_archive(transaction_id, - dest=self.application.export_dir) + 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")) + + 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) + 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 8ccc899f..d61e47e8 100644 --- a/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tosca.py +++ b/rwlaunchpad/plugins/rwlaunchpadtasklet/rift/tasklets/rwlaunchpad/tosca.py @@ -61,6 +61,7 @@ class ExportTosca(object): 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 @@ class ExportTosca(object): 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 @@ class ExportTosca(object): 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 @@ class ExportTosca(object): 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)