Merge "Update creating directly VNFFG and NS from descriptor template."
This commit is contained in:
81
api-ref/source/v1/samples/nss/nss-inline-create-request.json
Normal file
81
api-ref/source/v1/samples/nss/nss-inline-create-request.json
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"ns": {
|
||||
"name": "ns_test",
|
||||
"description": "sample NS",
|
||||
"tenant_id": "058079ca392749bfa58831e0467a5439",
|
||||
"attributes": {
|
||||
"param_values": {
|
||||
"nsd": {
|
||||
"vl2_name": "net0",
|
||||
"vl1_name": "net_mgmt"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nsd_template": {
|
||||
"imports": [
|
||||
"VNFD1",
|
||||
"VNFD2"
|
||||
],
|
||||
"tosca_definitions_version": "tosca_simple_profile_for_nfv_1_0_0",
|
||||
"topology_template": {
|
||||
"inputs": {
|
||||
"vl2_name": {
|
||||
"default": "net0",
|
||||
"type": "string",
|
||||
"description": "name of VL2 virtuallink"
|
||||
},
|
||||
"vl1_name": {
|
||||
"default": "net_mgmt",
|
||||
"type": "string",
|
||||
"description": "name of VL1 virtuallink"
|
||||
}
|
||||
},
|
||||
"node_templates": {
|
||||
"VNF1": {
|
||||
"type": "tosca.nodes.nfv.VNF1",
|
||||
"requirements": [
|
||||
{
|
||||
"virtualLink1": "VL1"
|
||||
},
|
||||
{
|
||||
"virtualLink2": "VL2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"VNF2": {
|
||||
"type": "tosca.nodes.nfv.VNF2"
|
||||
},
|
||||
"VL1": {
|
||||
"type": "tosca.nodes.nfv.VL",
|
||||
"properties": {
|
||||
"network_name": {
|
||||
"get_input": "vl1_name"
|
||||
},
|
||||
"vendor": "tacker"
|
||||
}
|
||||
},
|
||||
"VNF1": {
|
||||
"type": "tosca.nodes.nfv.VNF1",
|
||||
"requirements": [
|
||||
{
|
||||
"virtualLink1": "VL1"
|
||||
},
|
||||
{
|
||||
"virtualLink2": "VL2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"VL2": {
|
||||
"type": "tosca.nodes.nfv.VL",
|
||||
"properties": {
|
||||
"network_name": {
|
||||
"get_input": "vl2_name"
|
||||
},
|
||||
"vendor": "tacker"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"ns": {
|
||||
"status": "PENDING_CREATE",
|
||||
"created_at": "2017-07-14 17:03:33.596454",
|
||||
"description": "sample NS",
|
||||
"tenant_id": "058079ca392749bfa58831e0467a5439",
|
||||
"vim_id": "0e70ec23-6f32-420a-a039-2cdb2c20c329",
|
||||
"updated_at": null,
|
||||
"mgmt_urls": null,
|
||||
"vnf_ids": null,
|
||||
"error_reason": null,
|
||||
"nsd_id": "be18005d-5656-4d81-b499-6af4d4d8437f",
|
||||
"id": "ff35e3f0-0a11-4071-bce6-279fdf1c8bf9",
|
||||
"name": "ns_test"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"vnffg": {
|
||||
"tenant_id": "058079ca392749bfa58831e0467a5439",
|
||||
"name": "vnffg1",
|
||||
"vnf_mapping": {
|
||||
"VNFD2": "e40f29eb-b3e5-4c47-ab05-567be3a63fdb",
|
||||
"VNFD1": "e759aa4c-ae09-403a-8c04-90c77abfae56"
|
||||
},
|
||||
"symmetrical": false,
|
||||
"vnffgd_template": {
|
||||
"tosca_definitions_version": "tosca_simple_profile_for_nfv_1_0_0",
|
||||
"description": "Sample VNFFG template",
|
||||
"topology_template": {
|
||||
"description": "Sample VNFFG template",
|
||||
"node_templates": {
|
||||
"Forwarding_path1": {
|
||||
"type": "tosca.nodes.nfv.FP.Tacker",
|
||||
"description": "creates path (CP12->CP22)",
|
||||
"properties": {
|
||||
"id": 51,
|
||||
"policy": {
|
||||
"type": "ACL",
|
||||
"criteria": [
|
||||
{
|
||||
"network_src_port_id": "92011ca7-565d-408d-af67-09f21cdf9107"
|
||||
},
|
||||
{
|
||||
"ip_proto": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": [
|
||||
{
|
||||
"forwarder": "VNFD1",
|
||||
"capability": "CP12"
|
||||
},
|
||||
{
|
||||
"forwarder": "VNFD2",
|
||||
"capability": "CP22"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"groups": {
|
||||
"VNFFG1": {
|
||||
"type": "tosca.groups.nfv.VNFFG",
|
||||
"description": "HTTP to Corporate Net",
|
||||
"properties": {
|
||||
"vendor": "tacker",
|
||||
"version": 1.0,
|
||||
"number_of_endpoints": 2,
|
||||
"dependent_virtual_link": [
|
||||
"VL12",
|
||||
"VL22"
|
||||
],
|
||||
"connection_point": [
|
||||
"CP12",
|
||||
"CP22"
|
||||
],
|
||||
"constituent_vnfs": [
|
||||
"VNFD1",
|
||||
"VNFD2"
|
||||
]
|
||||
},
|
||||
"members": [
|
||||
"Forwarding_path1"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"vnffg": {
|
||||
"forwarding_paths": "a2d2d1dd-433f-47b7-89f8-be3cd6b2086a",
|
||||
"status": "PENDING_CREATE",
|
||||
"description": "",
|
||||
"tenant_id": "058079ca392749bfa58831e0467a5439",
|
||||
"vnffgd_id": "5263b036-8d11-410c-9417-6e0300456160",
|
||||
"vnf_mapping": {
|
||||
"VNFD2": "af76238b-75db-4f70-9ad7-bd286bb0f88a",
|
||||
"VNFD1": "dcda3482-1e75-4b37-8bdd-77c018a59cd7"
|
||||
},
|
||||
"attributes": {
|
||||
"vnffgd": {
|
||||
"imports": [
|
||||
"/opt/stack/tacker/tacker/tosca/lib/tacker_defs.yaml",
|
||||
"/opt/stack/tacker/tacker/tosca/lib/tacker_nfv_defs.yaml"
|
||||
],
|
||||
"description": "Sample VNFFG template",
|
||||
"topology_template": {
|
||||
"node_templates": {
|
||||
"Forwarding_path1": {
|
||||
"type": "tosca.nodes.nfv.FP.Tacker",
|
||||
"description": "creates path (CP12->CP22)",
|
||||
"properties": {
|
||||
"policy": {
|
||||
"type": "ACL",
|
||||
"criteria": [
|
||||
{
|
||||
"network_src_port_id": "9ec6bef0-5da9-4b04-bdc7-c57bc26bcdea"
|
||||
},
|
||||
{
|
||||
"ip_proto": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"path": [
|
||||
{
|
||||
"capability": "CP12",
|
||||
"forwarder": "VNFD1"
|
||||
},
|
||||
{
|
||||
"capability": "CP22",
|
||||
"forwarder": "VNFD2"
|
||||
}
|
||||
],
|
||||
"id": 51
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Sample VNFFG template",
|
||||
"groups": {
|
||||
"VNFFG1": {
|
||||
"type": "tosca.groups.nfv.VNFFG",
|
||||
"description": "HTTP to Corporate Net",
|
||||
"members": [
|
||||
"Forwarding_path1"
|
||||
],
|
||||
"properties": {
|
||||
"vendor": "tacker",
|
||||
"connection_point": [
|
||||
"CP12",
|
||||
"CP22"
|
||||
],
|
||||
"version": 1,
|
||||
"constituent_vnfs": [
|
||||
"VNFD1",
|
||||
"VNFD2"
|
||||
],
|
||||
"number_of_endpoints": 2,
|
||||
"dependent_virtual_link": [
|
||||
"VL12",
|
||||
"VL22"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tosca_definitions_version": "tosca_simple_profile_for_nfv_1_0_0"
|
||||
}
|
||||
},
|
||||
"id": "d86b2e7c-6e88-4d6e-ac1a-9a9ad56b48f5",
|
||||
"name": "vnffg1"
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ deploy a sample VNFD templates using vnf1.yaml and vnf2.yaml as mentioned in
|
||||
reference section.
|
||||
|
||||
::
|
||||
|
||||
tacker vnfd-create --vnfd-file vnfd1.yaml VNFD1
|
||||
|
||||
tacker vnfd-create --vnfd-file vnfd2.yaml VNFD2
|
||||
@@ -71,7 +72,9 @@ The following code represents sample NSD which instantiates the above VNFs
|
||||
In above NSD template VL1 and VL2 are substituting the virtuallinks of VNF1.
|
||||
To onboard the above NSD:
|
||||
|
||||
**tacker nsd-create --nsd-file <nsd file> <nsd name>**
|
||||
::
|
||||
|
||||
tacker nsd-create --nsd-file <nsd-file> <nsd-name>
|
||||
|
||||
Creating the NS
|
||||
~~~~~~~~~~~~~~~~
|
||||
@@ -81,7 +84,16 @@ VNFDS(which NS is substituting)
|
||||
|
||||
Tacker provides the following CLI to create NS:
|
||||
|
||||
**tacker ns-create --nsd-id <nsd-id> <ns-name>**
|
||||
::
|
||||
|
||||
tacker ns-create --nsd-id <nsd-id> <ns-name>
|
||||
|
||||
Or you can create directly a NS without creating onboarded NSD before by
|
||||
following CLI command:
|
||||
|
||||
::
|
||||
|
||||
tacker ns-create --nsd-template <nsd-file> <ns-name>
|
||||
|
||||
Reference
|
||||
~~~~~~~~~
|
||||
|
||||
@@ -29,9 +29,9 @@ Forwarding Graph Descriptors (VNFFGD). Please see the `devref guide
|
||||
/vnffgd_template_description.rst>`_ on VNFFGD to learn more about
|
||||
how a VNFFGD is defined.
|
||||
|
||||
After creating a VNFFGD, a VNFFG is instantiated by a separate Tacker
|
||||
command. This action will build the chain and classifier necessary to
|
||||
realize the VNFFG.
|
||||
VNFFG can be instantiated from VNFFGD or directly from VNFFGD template by
|
||||
separate Tacker commands. This action will build the chain and classifier
|
||||
necessary to realize the VNFFG.
|
||||
|
||||
Prerequisites
|
||||
~~~~~~~~~~~~~
|
||||
@@ -43,6 +43,22 @@ in order to use Tacker VNFFG. Networking-sfc also requires at least OVS 2.5
|
||||
.0, so also ensure that is installed. See the full `Networking-sfc guide
|
||||
<https://wiki.openstack.org/wiki/Neutron/ServiceInsertionAndChaining>`_.
|
||||
|
||||
A simple example of a service chain would be one that forces all traffice
|
||||
from HTTP client to HTTP server to go through VNFs that was created by
|
||||
VNFFG.
|
||||
|
||||
Firstly, HTTP client and HTTP server must be launched.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
net_id=$(openstack network list | grep net0 | awk '{print $2}')
|
||||
|
||||
openstack server create --flavor m1.tiny --image cirros-0.3.5-x86_64-disk \
|
||||
--nic net-id=$net_id http_client
|
||||
|
||||
openstack server create --flavor m1.tiny --image cirros-0.3.5-x86_64-disk \
|
||||
--nic net-id=$net_id http_server
|
||||
|
||||
Creating the VNFFGD
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -62,6 +78,22 @@ tosca-vnffgd-sample.yaml>`_.
|
||||
type: ACL
|
||||
criteria:
|
||||
- network_src_port_id: 640dfd77-c92b-45a3-b8fc-22712de480e1
|
||||
- destination_port_range: 80-1024
|
||||
- ip_proto: 6
|
||||
- ip_dst_prefix: 192.168.1.2/24
|
||||
|
||||
You can get network_src_port_id and IP destination address through
|
||||
OpenStack commands like bellow:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
client_ip=$(openstack server list | grep http_client | \
|
||||
grep -Eo '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
|
||||
|
||||
network_source_port_id=$(openstack port list | grep $client_ip | awk '{print $2}')
|
||||
|
||||
ip_dst=$(openstack server list | grep http_server | \
|
||||
grep -Eo '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
|
||||
|
||||
|
||||
This is required due to a limitation of Neutron networking-sfc and only
|
||||
@@ -71,7 +103,7 @@ Tacker provides the following CLI to create a VNFFGD:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffgd-create --vnffgd-file <vnffgd file> <vnffgd name>
|
||||
tacker vnffgd-create --vnffgd-file <vnffgd-file> <vnffgd-name>
|
||||
|
||||
|
||||
Creating the VNFFG
|
||||
@@ -82,24 +114,41 @@ VNFD types listed in the VNFFGD. Failure to do so will result in error when
|
||||
trying to create a VNFFG. Note, the VNFD you define **must** include the
|
||||
same Connection Point definitions as the ones you declared in your VNFFGD.
|
||||
|
||||
Refer the 'Getting Started' link below on how to create a VNFD and deploy a
|
||||
VNF:
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnfd-create --vnfd-file tosca-vnffg-vnfd1.yaml VNFD1
|
||||
tacker vnf-create --vnfd-name VNFD1 VNF1
|
||||
|
||||
tacker vnfd-create --vnfd-file tosca-vnffg-vnfd2.yaml VNFD2
|
||||
tacker vnf-create --vnfd-name VNFD2 VNF2
|
||||
|
||||
Refer the 'Getting Started' link below on how to create a VNFD and deploy
|
||||
2 VNFs: `VNF1`_ and `VNF2`_.
|
||||
|
||||
http://docs.openstack.org/developer/tacker/install/getting_started.html
|
||||
|
||||
Tacker provides the following CLI to create VNFFG:
|
||||
Tacker provides the following CLI to create VNFFG from VNFFGD:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-name <vnffgd name> \
|
||||
--vnf-mapping <vnf mapping> --symmetrical <boolean>
|
||||
tacker vnffg-create --vnffgd-name <vnffgd-name> \
|
||||
--vnf-mapping <vnf-mapping> --symmetrical <boolean> <vnffg-name>
|
||||
|
||||
or you can create directly VNFFG from vnffgd template without initiating
|
||||
VNFFGD.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-template <vnffgd-template> \
|
||||
--vnf-mapping <vnf-mapping> --symmetrical <boolean> <vnffg-name>
|
||||
|
||||
If you use a parameterized vnffg template:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-name <vnffgd name> \
|
||||
--param-file <param file> --vnf-mapping <vnf mapping> \
|
||||
--symmetrical <boolean>
|
||||
tacker vnffg-create --vnffgd-name <vnffgd-name> \
|
||||
--param-file <param-file> --vnf-mapping <vnf-mapping> \
|
||||
--symmetrical <boolean> <vnffg-name>
|
||||
|
||||
Here,
|
||||
|
||||
@@ -109,18 +158,23 @@ Here,
|
||||
* symmetrical - True/False
|
||||
|
||||
VNF Mapping is used to declare which exact VNF instance to be used for
|
||||
each VNF in the Forwarding Path. For example, imagine a Forwarding Path
|
||||
'path' which includes VNF1 and VNF2 VNFDs. Two VNF instances already exist
|
||||
(one from each VNFD): '91e32c20-6d1f-47a4-9ba7-08f5e5effe07',
|
||||
'7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'. The following command would then
|
||||
map each VNFD defined in the VNFFGD Forwarding Path to the desired VNF
|
||||
instance:
|
||||
each VNF in the Forwarding Path. The following command would list VNFs
|
||||
in Tacker and then map each VNFD defined in the VNFFGD Forwarding Path
|
||||
to the desired VNF instance:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-name myvnffgd \
|
||||
--vnf-mapping VNF1:'91e32c20-6d1f-47a4-9ba7-08f5e5effe07', \
|
||||
VNF2:'7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'
|
||||
tacker vnf-list
|
||||
|
||||
+--------------------------------------+------+---------------------------+--------+--------------------------------------+--------------------------------------+
|
||||
| id | name | mgmt_url | status | vim_id | vnfd_id |
|
||||
+--------------------------------------+------+---------------------------+--------+--------------------------------------+--------------------------------------+
|
||||
| 7168062e-9fa1-4203-8cb7-f5c99ff3ee1b | VNF2 | {"VDU1": "192.168.1.5"} | ACTIVE | 0e70ec23-6f32-420a-a039-2cdb2c20c329 | ea842879-5a7a-4f29-a8b0-528b2ad3b027 |
|
||||
| 91e32c20-6d1f-47a4-9ba7-08f5e5effe07 | VNF1 | {"VDU1": "192.168.1.7"} | ACTIVE | 0e70ec23-6f32-420a-a039-2cdb2c20c329 | 27795330-62a7-406d-9443-2daad76e674b |
|
||||
+--------------------------------------+------+---------------------------+--------+--------------------------------------+--------------------------------------+
|
||||
|
||||
tacker vnffg-create --vnffgd-name myvnffgd --vnf-mapping \
|
||||
VNFD1:'91e32c20-6d1f-47a4-9ba7-08f5e5effe07',VNF2:'7168062e-9fa1-4203-8cb7-f5c99ff3ee1b' myvnffg
|
||||
|
||||
Alternatively, if no vnf-mapping is provided then Tacker VNFFG will attempt
|
||||
to search for VNF instances derived from the given VNFDs in the VNFFGD. If
|
||||
@@ -147,7 +201,7 @@ The value of a parameterized attribute can be specified like *{get_input foo}*
|
||||
in the TOSCA VNFFGD template. The corresponding param-file in the following
|
||||
YAML format can be provided in the vnffg-create command,
|
||||
|
||||
::
|
||||
.. code-block:: console
|
||||
|
||||
{
|
||||
foo: bar
|
||||
@@ -155,10 +209,11 @@ YAML format can be provided in the vnffg-create command,
|
||||
|
||||
VNFFG command with parameter file:
|
||||
|
||||
**tacker vnffg-create --vnffgd-name myvnffgd**
|
||||
**--vnf-mapping VNF1:'91e32c20-6d1f-47a4-9ba7-08f5e5effe07',**
|
||||
**VNF2:'7168062e-9fa1-4203-8cb7-f5c99ff3ee1b'**
|
||||
**--param-file cust-site-x-param.yaml**
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
tacker vnffg-create --vnffgd-name vnffgd-param --vnf-mapping VNFD1:'91e32c20-6d1f-47a4-9ba7-08f5e5effe07',\
|
||||
VNFD2:'7168062e-9fa1-4203-8cb7-f5c99ff3ee1b' --param-file vnffg-param-file.yaml myvnffg
|
||||
|
||||
|
||||
See `VNFFGD template samples with parameter support <https://github.com/
|
||||
@@ -192,3 +247,6 @@ Known Issues and Limitations
|
||||
'network_name'
|
||||
- NSH attributes not yet supported
|
||||
- Symmetrical is not supported by driver yet
|
||||
|
||||
.. _VNF1: https://github.com/openstack/tacker/blob/master/samples/tosca-templates/vnffgd/tosca-vnffg-vnfd1.yaml
|
||||
.. _VNF2: https://github.com/openstack/tacker/blob/master/samples/tosca-templates/vnffgd/tosca-vnffg-vnfd2.yaml
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Support to create directly VNFFG and NS from its descriptor template
|
||||
without creating VNFFGD and NSD.
|
||||
@@ -565,8 +565,16 @@ class Controller(object):
|
||||
for rule in attr_vals['validate']:
|
||||
# skip validating vnfd_id when vnfd_template is specified to
|
||||
# create vnf
|
||||
if resource == 'vnf' and 'vnfd_template' in body['vnf'] and \
|
||||
attr == "vnfd_id" and is_create:
|
||||
if (resource == 'vnf') and ('vnfd_template' in body['vnf'])\
|
||||
and (attr == "vnfd_id") and is_create:
|
||||
continue
|
||||
# skip validating vnffgd_id when vnffgd_template is provided
|
||||
if (resource == 'vnffg') and ('vnffgd_template' in body['vnffg'])\
|
||||
and (attr == 'vnffgd_id') and is_create:
|
||||
continue
|
||||
# skip validating nsd_id when nsd_template is provided
|
||||
if (resource == 'ns') and ('nsd_template' in body['ns'])\
|
||||
and (attr == 'nsd_id') and is_create:
|
||||
continue
|
||||
res = attributes.validators[rule](res_dict[attr],
|
||||
attr_vals['validate'][rule])
|
||||
|
||||
@@ -1 +1 @@
|
||||
f5c1c3b0f6b4
|
||||
e9a1e47fb0b5
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Copyright 2017 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
"""add onboarded status for vnffgd and nsd
|
||||
|
||||
Revision ID: e9a1e47fb0b5
|
||||
Revises: f5c1c3b0f6b4
|
||||
Create Date: 2017-07-17 10:02:37.572587
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'e9a1e47fb0b5'
|
||||
down_revision = 'f5c1c3b0f6b4'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
op.add_column('vnffgtemplates',
|
||||
sa.Column('template_source',
|
||||
sa.String(length=255),
|
||||
server_default='onboarded'))
|
||||
op.execute("UPDATE vnffgtemplates set template_source='onboarded'"
|
||||
" WHERE template_source is NULL")
|
||||
|
||||
op.add_column('nsd',
|
||||
sa.Column('template_source',
|
||||
sa.String(length=255),
|
||||
server_default='onboarded'))
|
||||
op.execute("UPDATE nsd set template_source='onboarded'"
|
||||
" WHERE template_source is NULL")
|
||||
@@ -12,11 +12,12 @@
|
||||
|
||||
import ast
|
||||
from datetime import datetime
|
||||
import uuid
|
||||
|
||||
from oslo_db.exception import DBDuplicateEntry
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
from six import iteritems
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
@@ -54,6 +55,9 @@ class NSD(model_base.BASE, models_v1.HasId, models_v1.HasTenant,
|
||||
description = sa.Column(sa.Text)
|
||||
vnfds = sa.Column(types.Json, nullable=True)
|
||||
|
||||
# Nsd template source - onboarded
|
||||
template_source = sa.Column(sa.String(255), server_default='onboarded')
|
||||
|
||||
# (key, value) pair to spin up
|
||||
attributes = orm.relationship('NSDAttribute',
|
||||
backref='nsd')
|
||||
@@ -146,7 +150,7 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||
'attributes': self._make_attributes_dict(nsd['attributes']),
|
||||
}
|
||||
key_list = ('id', 'tenant_id', 'name', 'description',
|
||||
'created_at', 'updated_at', 'vnfds')
|
||||
'created_at', 'updated_at', 'vnfds', 'template_source')
|
||||
res.update((key, nsd[key]) for key in key_list)
|
||||
return self._fields(res, fields)
|
||||
|
||||
@@ -167,21 +171,23 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||
nsd = nsd['nsd']
|
||||
LOG.debug('nsd %s', nsd)
|
||||
tenant_id = self._get_tenant_id_for_create(context, nsd)
|
||||
template_source = nsd.get('template_source')
|
||||
|
||||
try:
|
||||
with context.session.begin(subtransactions=True):
|
||||
nsd_id = uuidutils.generate_uuid()
|
||||
nsd_id = str(uuid.uuid4())
|
||||
nsd_db = NSD(
|
||||
id=nsd_id,
|
||||
tenant_id=tenant_id,
|
||||
name=nsd.get('name'),
|
||||
vnfds=vnfds,
|
||||
description=nsd.get('description'),
|
||||
deleted_at=datetime.min)
|
||||
deleted_at=datetime.min,
|
||||
template_source=template_source)
|
||||
context.session.add(nsd_db)
|
||||
for (key, value) in nsd.get('attributes', {}).items():
|
||||
attribute_db = NSDAttribute(
|
||||
id=uuidutils.generate_uuid(),
|
||||
id=str(uuid.uuid4()),
|
||||
nsd_id=nsd_id,
|
||||
key=key,
|
||||
value=value)
|
||||
@@ -233,6 +239,9 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||
return self._make_nsd_dict(nsd_db)
|
||||
|
||||
def get_nsds(self, context, filters, fields=None):
|
||||
if ('template_source' in filters) and \
|
||||
(filters['template_source'][0] == 'all'):
|
||||
filters.pop('template_source')
|
||||
return self._get_collection(context, NSD,
|
||||
self._make_nsd_dict,
|
||||
filters=filters, fields=fields)
|
||||
@@ -245,7 +254,7 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||
nsd_id = ns['nsd_id']
|
||||
vim_id = ns['vim_id']
|
||||
name = ns.get('name')
|
||||
ns_id = uuidutils.generate_uuid()
|
||||
ns_id = str(uuid.uuid4())
|
||||
try:
|
||||
with context.session.begin(subtransactions=True):
|
||||
nsd_db = self._get_resource(context, NSD,
|
||||
@@ -283,7 +292,7 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||
mgmt_urls = dict()
|
||||
vnf_ids = dict()
|
||||
if len(output) > 0:
|
||||
for vnfd_name, vnfd_val in (vnfd_dict).items():
|
||||
for vnfd_name, vnfd_val in iteritems(vnfd_dict):
|
||||
for instance in vnfd_val['instances']:
|
||||
if 'mgmt_url_' + instance in output:
|
||||
mgmt_urls[instance] = ast.literal_eval(
|
||||
@@ -332,6 +341,8 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||
|
||||
def delete_ns_post(self, context, ns_id, mistral_obj,
|
||||
error_reason, soft_delete=True):
|
||||
ns = self.get_ns(context, ns_id)
|
||||
nsd_id = ns.get('nsd_id')
|
||||
with context.session.begin(subtransactions=True):
|
||||
query = (
|
||||
self._model_query(context, NS).
|
||||
@@ -359,6 +370,9 @@ class NSPluginDb(network_service.NSPluginBase, db_base.CommonDbMixin):
|
||||
details="ns Delete Complete")
|
||||
else:
|
||||
query.delete()
|
||||
template_db = self._get_resource(context, NSD, nsd_id)
|
||||
if template_db.get('template_source') == 'inline':
|
||||
self.delete_nsd(context, nsd_id)
|
||||
|
||||
def get_ns(self, context, ns_id, fields=None):
|
||||
ns_db = self._get_resource(context, NS, ns_id)
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
|
||||
import random
|
||||
import sqlalchemy as sa
|
||||
import uuid
|
||||
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import uuidutils
|
||||
from six import iteritems
|
||||
from sqlalchemy import orm
|
||||
from sqlalchemy.orm import exc as orm_exc
|
||||
from tacker.db import db_base
|
||||
@@ -72,6 +73,9 @@ class VnffgTemplate(model_base.BASE, models_v1.HasId, models_v1.HasTenant):
|
||||
# Vnffg template
|
||||
template = sa.Column(types.Json)
|
||||
|
||||
# Vnffgd template source - onboarded
|
||||
template_source = sa.Column(sa.String(255), server_default='onboarded')
|
||||
|
||||
|
||||
class Vnffg(model_base.BASE, models_v1.HasTenant, models_v1.HasId):
|
||||
"""VNF Forwarding Graph Data Model"""
|
||||
@@ -191,8 +195,8 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
|
||||
def create_vnffg(self, context, vnffg):
|
||||
vnffg_dict = self._create_vnffg_pre(context, vnffg)
|
||||
sfc_instance = uuidutils.generate_uuid()
|
||||
fc_instance = uuidutils.generate_uuid()
|
||||
sfc_instance = str(uuid.uuid4())
|
||||
fc_instance = str(uuid.uuid4())
|
||||
self._create_vnffg_post(context, sfc_instance,
|
||||
fc_instance, vnffg_dict)
|
||||
self._create_vnffg_status(context, vnffg_dict)
|
||||
@@ -219,15 +223,17 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
template = vnffgd['vnffgd']
|
||||
LOG.debug('template %s', template)
|
||||
tenant_id = self._get_tenant_id_for_create(context, template)
|
||||
template_source = template.get('template_source')
|
||||
|
||||
with context.session.begin(subtransactions=True):
|
||||
template_id = uuidutils.generate_uuid()
|
||||
template_id = str(uuid.uuid4())
|
||||
template_db = VnffgTemplate(
|
||||
id=template_id,
|
||||
tenant_id=tenant_id,
|
||||
name=template.get('name'),
|
||||
description=template.get('description'),
|
||||
template=template.get('template'))
|
||||
template=template.get('template'),
|
||||
template_source=template_source)
|
||||
context.session.add(template_db)
|
||||
|
||||
LOG.debug('template_db %(template_db)s',
|
||||
@@ -240,6 +246,9 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
return self._make_template_dict(template_db, fields)
|
||||
|
||||
def get_vnffgds(self, context, filters=None, fields=None):
|
||||
if ('template_source' in filters) and \
|
||||
(filters['template_source'][0] == 'all'):
|
||||
filters.pop('template_source')
|
||||
return self._get_collection(context, VnffgTemplate,
|
||||
self._make_template_dict,
|
||||
filters=filters, fields=fields)
|
||||
@@ -287,7 +296,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
if 'get_input' not in str(original):
|
||||
return
|
||||
if isinstance(original, dict):
|
||||
for key_, value in (original).items():
|
||||
for key_, value in iteritems(original):
|
||||
if isinstance(value, dict) and 'get_input' in value:
|
||||
if value['get_input'] in paramvalues:
|
||||
original[key_] = paramvalues[value['get_input']]
|
||||
@@ -323,7 +332,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
LOG.debug('vnffg %s', vnffg)
|
||||
tenant_id = self._get_tenant_id_for_create(context, vnffg)
|
||||
name = vnffg.get('name')
|
||||
vnffg_id = vnffg.get('id') or uuidutils.generate_uuid()
|
||||
vnffg_id = vnffg.get('id') or str(uuid.uuid4())
|
||||
template_id = vnffg['vnffgd_id']
|
||||
symmetrical = vnffg['symmetrical']
|
||||
|
||||
@@ -361,9 +370,9 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
status=constants.PENDING_CREATE)
|
||||
context.session.add(vnffg_db)
|
||||
|
||||
nfp_id = uuidutils.generate_uuid()
|
||||
sfc_id = uuidutils.generate_uuid()
|
||||
classifier_id = uuidutils.generate_uuid()
|
||||
nfp_id = str(uuid.uuid4())
|
||||
sfc_id = str(uuid.uuid4())
|
||||
classifier_id = str(uuid.uuid4())
|
||||
|
||||
nfp_db = VnffgNfp(id=nfp_id, vnffg_id=vnffg_id,
|
||||
tenant_id=tenant_id,
|
||||
@@ -399,7 +408,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
LOG.debug('acl_match %s', match)
|
||||
|
||||
match_db_table = ACLMatchCriteria(
|
||||
id=uuidutils.generate_uuid(),
|
||||
id=str(uuid.uuid4()),
|
||||
vnffgc_id=classifier_id,
|
||||
**match)
|
||||
|
||||
@@ -662,7 +671,7 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
"""
|
||||
# this should be overridden with driver call to find ID given name
|
||||
# for resource
|
||||
return uuidutils.generate_uuid()
|
||||
return str(uuid.uuid4())
|
||||
|
||||
# called internally, not by REST API
|
||||
# instance_id = None means error on creation
|
||||
@@ -902,9 +911,17 @@ class VnffgPluginDbMixin(vnffg.VNFFGPluginBase, db_base.CommonDbMixin):
|
||||
nfp_query.delete()
|
||||
vnffg_query.delete()
|
||||
|
||||
vnffgd_id = vnffg.get('vnffgd_id')
|
||||
template_db = self._get_resource(context, VnffgTemplate,
|
||||
vnffgd_id)
|
||||
|
||||
if template_db.get('template_source') == 'inline':
|
||||
self.delete_vnffgd(context, vnffgd_id)
|
||||
|
||||
def _make_template_dict(self, template, fields=None):
|
||||
res = {}
|
||||
key_list = ('id', 'tenant_id', 'name', 'description', 'template')
|
||||
key_list = ('id', 'tenant_id', 'name', 'description', 'template',
|
||||
'template_source')
|
||||
res.update((key, template[key]) for key in key_list)
|
||||
return self._fields(res, fields)
|
||||
|
||||
|
||||
@@ -367,6 +367,12 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'is_visible': True,
|
||||
'default': None,
|
||||
},
|
||||
'template_source': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
'default': 'onboarded'
|
||||
}
|
||||
},
|
||||
|
||||
'vnffgs': {
|
||||
@@ -389,6 +395,7 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True,
|
||||
'default': None
|
||||
},
|
||||
'name': {
|
||||
'allow_post': True,
|
||||
@@ -436,6 +443,13 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
'vnffgd_template': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'validate': {'type:dict_or_nodata': None},
|
||||
'is_visible': True,
|
||||
'default': None,
|
||||
},
|
||||
},
|
||||
|
||||
'nfps': {
|
||||
@@ -636,6 +650,12 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'is_visible': True,
|
||||
'default': None,
|
||||
},
|
||||
'template_source': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
'default': 'onboarded'
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
@@ -689,6 +709,7 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'allow_put': False,
|
||||
'validate': {'type:uuid': None},
|
||||
'is_visible': True,
|
||||
'default': None,
|
||||
},
|
||||
'vim_id': {
|
||||
'allow_post': True,
|
||||
@@ -722,6 +743,13 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'validate': {'type:dict_or_nodata': None},
|
||||
'is_visible': True,
|
||||
},
|
||||
'nsd_template': {
|
||||
'allow_post': True,
|
||||
'allow_put': False,
|
||||
'validate': {'type:dict_or_nodata': None},
|
||||
'is_visible': True,
|
||||
'default': None,
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -266,6 +266,12 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||
def create_vnffgd(self, context, vnffgd):
|
||||
template = vnffgd['vnffgd']
|
||||
|
||||
if 'template_source' in template:
|
||||
template_source = template.get('template_source')
|
||||
else:
|
||||
template_source = 'onboarded'
|
||||
vnffgd['vnffgd']['template_source'] = template_source
|
||||
|
||||
if 'vnffgd' not in template.get('template'):
|
||||
raise nfvo.VnffgdInvalidTemplate(template=template.get('template'))
|
||||
else:
|
||||
@@ -279,6 +285,20 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||
|
||||
@log.log
|
||||
def create_vnffg(self, context, vnffg):
|
||||
vnffg_info = vnffg['vnffg']
|
||||
name = vnffg_info['name']
|
||||
|
||||
if vnffg_info.get('vnffgd_template'):
|
||||
vnffgd_name = utils.generate_resource_name(name, 'inline')
|
||||
vnffgd = {'vnffgd': {'tenant_id': vnffg_info['tenant_id'],
|
||||
'name': vnffgd_name,
|
||||
'template': {
|
||||
'vnffgd': vnffg_info['vnffgd_template']},
|
||||
'template_source': 'inline',
|
||||
'description': vnffg_info['description']}}
|
||||
vnffg_info['vnffgd_id'] = \
|
||||
self.create_vnffgd(context, vnffgd).get('id')
|
||||
|
||||
vnffg_dict = super(NfvoPlugin, self)._create_vnffg_pre(context, vnffg)
|
||||
nfp = super(NfvoPlugin, self).get_nfp(context,
|
||||
vnffg_dict['forwarding_paths'])
|
||||
@@ -502,6 +522,12 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||
template)
|
||||
LOG.debug('nsd %s', nsd_data)
|
||||
|
||||
if 'template_source' in nsd_data:
|
||||
template_source = nsd_data.get('template_source')
|
||||
else:
|
||||
template_source = "onboarded"
|
||||
nsd['nsd']['template_source'] = template_source
|
||||
|
||||
self._parse_template_input(context, nsd)
|
||||
return super(NfvoPlugin, self).create_nsd(
|
||||
context, nsd)
|
||||
@@ -576,6 +602,19 @@ class NfvoPlugin(nfvo_db_plugin.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin,
|
||||
VNFs will actually substitute their requirements.
|
||||
step-3: Create mistral workflow and execute the workflow
|
||||
"""
|
||||
ns_info = ns['ns']
|
||||
name = ns_info['name']
|
||||
|
||||
if ns_info.get('nsd_template'):
|
||||
nsd_name = utils.generate_resource_name(name, 'inline')
|
||||
nsd = {'nsd': {
|
||||
'attributes': {'nsd': ns_info['nsd_template']},
|
||||
'description': ns_info['description'],
|
||||
'name': nsd_name,
|
||||
'template_source': 'inline',
|
||||
'tenant_id': ns_info['tenant_id']}}
|
||||
ns_info['nsd_id'] = self.create_nsd(context, nsd).get('id')
|
||||
|
||||
nsd = self.get_nsd(context, ns['ns']['nsd_id'])
|
||||
nsd_dict = yaml.safe_load(nsd['attributes']['nsd'])
|
||||
vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM']
|
||||
|
||||
@@ -101,33 +101,56 @@ class NsdTestCreate(base.BaseTackerTest):
|
||||
int(time.time()) - start_time) > timeout):
|
||||
raise Exception("Failed with status: %s" % status)
|
||||
|
||||
def _test_create_delete_ns(self, nsd_file, ns_name):
|
||||
def _test_create_delete_ns(self, nsd_file, ns_name,
|
||||
template_source='onboarded'):
|
||||
vnfd1_id = self._test_create_tosca_vnfd(
|
||||
'test-ns-vnfd1.yaml',
|
||||
'test-ns-vnfd1')
|
||||
vnfd2_id = self._test_create_tosca_vnfd(
|
||||
'test-ns-vnfd2.yaml',
|
||||
'test-ns-vnfd2')
|
||||
nsd_id = self._test_create_nsd(
|
||||
nsd_file,
|
||||
'test-ns-nsd')
|
||||
ns_arg = {'ns': {'nsd_id': nsd_id, 'name': ns_name,
|
||||
'attributes': {"param_values": {"nsd":
|
||||
{"vl2_name": "net0",
|
||||
"vl1_name": "net_mgmt"}}}}}
|
||||
ns_instance = self.client.create_ns(body=ns_arg)
|
||||
ns_id = ns_instance['ns']['id']
|
||||
|
||||
if template_source == 'onboarded':
|
||||
nsd_id = self._test_create_nsd(
|
||||
nsd_file,
|
||||
'test-ns-nsd')
|
||||
ns_arg = {'ns': {
|
||||
'nsd_id': nsd_id,
|
||||
'name': ns_name,
|
||||
'attributes': {"param_values": {
|
||||
"nsd": {
|
||||
"vl2_name": "net0",
|
||||
"vl1_name": "net_mgmt"}}}}}
|
||||
ns_instance = self.client.create_ns(body=ns_arg)
|
||||
ns_id = ns_instance['ns']['id']
|
||||
|
||||
if template_source == 'inline':
|
||||
input_yaml = read_file(nsd_file)
|
||||
template = yaml.safe_load(input_yaml)
|
||||
ns_arg = {'ns': {
|
||||
'name': ns_name,
|
||||
'attributes': {"param_values": {
|
||||
"nsd": {
|
||||
"vl2_name": "net0",
|
||||
"vl1_name": "net_mgmt"}}},
|
||||
'nsd_template': template}}
|
||||
ns_instance = self.client.create_ns(body=ns_arg)
|
||||
ns_id = ns_instance['ns']['id']
|
||||
|
||||
self._wait_until_ns_status(ns_id, 'ACTIVE',
|
||||
constants.NS_CREATE_TIMEOUT,
|
||||
constants.ACTIVE_SLEEP_TIME)
|
||||
ns_show_out = self.client.show_ns(ns_id)['ns']
|
||||
self.assertIsNotNone(ns_show_out['mgmt_urls'])
|
||||
|
||||
try:
|
||||
self.client.delete_ns(ns_id)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
print("Exception:", e)
|
||||
assert False, "ns Delete failed"
|
||||
self._wait_until_ns_delete(ns_id, constants.NS_DELETE_TIMEOUT)
|
||||
self._test_delete_nsd(nsd_id)
|
||||
if template_source == 'onboarded':
|
||||
self._wait_until_ns_delete(ns_id, constants.NS_DELETE_TIMEOUT)
|
||||
self._test_delete_nsd(nsd_id)
|
||||
self._test_delete_vnfd(vnfd1_id)
|
||||
self._test_delete_vnfd(vnfd2_id)
|
||||
|
||||
@@ -147,4 +170,9 @@ class NsdTestCreate(base.BaseTackerTest):
|
||||
|
||||
def test_create_delete_network_service(self):
|
||||
self._test_create_delete_ns('test-ns-nsd.yaml',
|
||||
'test-ns')
|
||||
'test-ns-onboarded',
|
||||
template_source='onboarded')
|
||||
time.sleep(1)
|
||||
self._test_create_delete_ns('test-ns-nsd.yaml',
|
||||
'test-ns-inline',
|
||||
template_source='inline')
|
||||
|
||||
@@ -165,14 +165,23 @@ def get_vim_auth_obj():
|
||||
|
||||
|
||||
def get_dummy_vnffgd_obj():
|
||||
return {u'vnffgd': {'name': 'dummy_vnfd',
|
||||
return {u'vnffgd': {'name': 'dummy_vnffgd',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
u'template': {u'vnffgd': vnffgd_tosca_template},
|
||||
'description': 'dummy_vnfd_description'}}
|
||||
'description': 'dummy_vnffgd_description',
|
||||
'template_source': 'onboarded'}}
|
||||
|
||||
|
||||
def get_dummy_vnffgd_obj_inline():
|
||||
return {u'vnffgd': {'name': 'dummy_vnffgd_inline',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
u'template': {u'vnffgd': vnffgd_tosca_template},
|
||||
'description': 'dummy_vnffgd_description_inline',
|
||||
'template_source': 'inline'}}
|
||||
|
||||
|
||||
def get_dummy_vnffg_obj():
|
||||
return {'vnffg': {'description': 'dummy_vnf_description',
|
||||
return {'vnffg': {'description': 'dummy_vnffg_description',
|
||||
'vnffgd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'name': 'dummy_vnffg',
|
||||
@@ -181,6 +190,16 @@ def get_dummy_vnffg_obj():
|
||||
'symmetrical': False}}
|
||||
|
||||
|
||||
def get_dummy_vnffg_obj_inline():
|
||||
return {'vnffg': {'description': 'dummy_vnffg_description_inline',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'name': 'dummy_vnffg_inline',
|
||||
u'attributes': {u'template': vnffgd_tosca_template},
|
||||
'vnf_mapping': {},
|
||||
'symmetrical': False,
|
||||
'vnffgd_template': vnffgd_tosca_template}}
|
||||
|
||||
|
||||
def get_dummy_vnffg_param_obj():
|
||||
return {'vnffg': {'description': 'dummy_vnf_description',
|
||||
'vnffgd_id': u'eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
@@ -234,10 +253,19 @@ def get_dummy_vnffg_obj_vnf_mapping():
|
||||
|
||||
|
||||
def get_dummy_nsd_obj():
|
||||
return {'nsd': {'description': 'dummy nsd description',
|
||||
return {'nsd': {'description': 'dummy_nsd_description',
|
||||
'name': 'dummy_NSD',
|
||||
'tenant_id': u'8819a1542a5948b68f94d4be0fd50496',
|
||||
'attributes': {u'nsd': nsd_tosca_template}}}
|
||||
'attributes': {u'nsd': nsd_tosca_template},
|
||||
'template_source': 'onboarded'}}
|
||||
|
||||
|
||||
def get_dummy_nsd_obj_inline():
|
||||
return {'nsd': {'description': 'dummy_nsd_description_inline',
|
||||
'name': 'dummy_NSD_inline',
|
||||
'tenant_id': u'8819a1542a5948b68f94d4be0fd50496',
|
||||
'attributes': {u'nsd': nsd_tosca_template},
|
||||
'template_source': 'inline'}}
|
||||
|
||||
|
||||
def get_dummy_ns_obj():
|
||||
@@ -252,6 +280,18 @@ def get_dummy_ns_obj():
|
||||
'vl2_name': 'net0'}}}}}
|
||||
|
||||
|
||||
def get_dummy_ns_obj_inline():
|
||||
return {'ns': {'description': 'dummy_ns_description_inline',
|
||||
'id': u'ff35e3f0-0a11-4071-bce6-279fdf1c8bf9',
|
||||
'vim_id': u'6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
'tenant_id': u'ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
'name': 'dummy_ns_inline',
|
||||
'attributes': {
|
||||
'param_values': {'nsd': {'vl1_name': 'net_mgmt',
|
||||
'vl2_name': 'net0'}}},
|
||||
'nsd_template': nsd_tosca_template}}
|
||||
|
||||
|
||||
def get_dummy_ns_obj_2():
|
||||
return {'ns': {'description': 'dummy_ns_description',
|
||||
'id': u'ba6bf017-f6f7-45f1-a280-57b073bf78ea',
|
||||
|
||||
@@ -17,10 +17,10 @@ import codecs
|
||||
from datetime import datetime
|
||||
import mock
|
||||
import os
|
||||
import uuid
|
||||
|
||||
|
||||
from mock import patch
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker import context
|
||||
from tacker.db.common_services import common_services_db_plugin
|
||||
@@ -57,7 +57,7 @@ class FakeDriverManager(mock.Mock):
|
||||
def invoke(self, *args, **kwargs):
|
||||
if any(x in ['create', 'create_chain', 'create_flow_classifier'] for
|
||||
x in args):
|
||||
return uuidutils.generate_uuid()
|
||||
return str(uuid.uuid4())
|
||||
elif 'execute_workflow' in args:
|
||||
mock_execution = mock.Mock()
|
||||
mock_execution.id.return_value = \
|
||||
@@ -366,7 +366,21 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
name='fake_template',
|
||||
description='fake_template_description',
|
||||
template={u'vnffgd': utils.vnffgd_tosca_template})
|
||||
template={u'vnffgd': utils.vnffgd_tosca_template},
|
||||
template_source='onboarded')
|
||||
session.add(vnffg_template)
|
||||
session.flush()
|
||||
return vnffg_template
|
||||
|
||||
def _insert_dummy_vnffg_template_inline(self):
|
||||
session = self.context.session
|
||||
vnffg_template = vnffg_db.VnffgTemplate(
|
||||
id='11da9f20-9347-4283-bc68-eb98061ef8f7',
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
name='dummy_vnffgd_inline',
|
||||
description='dummy_vnffgd_description_inline',
|
||||
template={u'vnffgd': utils.vnffgd_tosca_template},
|
||||
template_source='inline')
|
||||
session.add(vnffg_template)
|
||||
session.flush()
|
||||
return vnffg_template
|
||||
@@ -501,6 +515,16 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertIn('template', result)
|
||||
self.assertIn('template_source', result)
|
||||
self.assertEqual('onboarded', result['template_source'])
|
||||
|
||||
def test_create_vnffgd_inline(self):
|
||||
vnffgd_obj = utils.get_dummy_vnffgd_obj_inline()
|
||||
result = self.nfvo_plugin.create_vnffgd(self.context, vnffgd_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertIn('template', result)
|
||||
self.assertEqual('inline', result['template_source'])
|
||||
|
||||
def test_create_vnffg_abstract_types(self):
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
@@ -523,6 +547,32 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
symmetrical=mock.ANY
|
||||
)
|
||||
|
||||
@mock.patch('tacker.nfvo.nfvo_plugin.NfvoPlugin.create_vnffgd')
|
||||
def test_create_vnffg_abstract_types_inline(self, mock_create_vnffgd):
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock.patch('tacker.common.driver_manager.DriverManager',
|
||||
side_effect=FakeDriverManager()).start()
|
||||
mock_create_vnffgd.return_value = {'id':
|
||||
'11da9f20-9347-4283-bc68-eb98061ef8f7'}
|
||||
self._insert_dummy_vnffg_template_inline()
|
||||
vnffg_obj = utils.get_dummy_vnffg_obj_inline()
|
||||
result = self.nfvo_plugin.create_vnffg(self.context, vnffg_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertIn('status', result)
|
||||
self.assertEqual('PENDING_CREATE', result['status'])
|
||||
self.assertEqual('dummy_vnffg_inline', result['name'])
|
||||
mock_create_vnffgd.assert_called_once_with(mock.ANY, mock.ANY)
|
||||
self._driver_manager.invoke.assert_called_with(mock.ANY, mock.ANY,
|
||||
name=mock.ANY,
|
||||
vnfs=mock.ANY,
|
||||
fc_id=mock.ANY,
|
||||
auth_attr=mock.ANY,
|
||||
symmetrical=mock.ANY
|
||||
)
|
||||
|
||||
def test_create_vnffg_param_values(self):
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
@@ -669,11 +719,12 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
vnfds={'tosca.nodes.nfv.VNF1': 'vnf1',
|
||||
'tosca.nodes.nfv.VNF2': 'vnf2'},
|
||||
description='fake_nsd_template_description',
|
||||
deleted_at=datetime.min)
|
||||
deleted_at=datetime.min,
|
||||
template_source='onboarded')
|
||||
session.add(nsd_template)
|
||||
for (key, value) in attributes.items():
|
||||
attribute_db = ns_db.NSDAttribute(
|
||||
id=uuidutils.generate_uuid(),
|
||||
id=str(uuid.uuid4()),
|
||||
nsd_id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
key=key,
|
||||
value=value)
|
||||
@@ -681,16 +732,53 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
session.flush()
|
||||
return nsd_template
|
||||
|
||||
def _insert_dummy_ns_template_inline(self):
|
||||
session = self.context.session
|
||||
attributes = {
|
||||
u'nsd': 'imports: [VNF1, VNF2]\ntopology_template:\n inputs:\n '
|
||||
' vl1_name: {default: net_mgmt, description: name of VL1'
|
||||
' virtuallink, type: string}\n vl2_name: {default: '
|
||||
'net0, description: name of VL2 virtuallink, type: string'
|
||||
'}\n node_templates:\n VL1:\n properties:\n '
|
||||
' network_name: {get_input: vl1_name}\n vendor: '
|
||||
'tacker\n type: tosca.nodes.nfv.VL\n VL2:\n '
|
||||
'properties:\n network_name: {get_input: vl2_name}'
|
||||
'\n vendor: tacker\n type: tosca.nodes.nfv.VL'
|
||||
'\n VNF1:\n requirements:\n - {virtualLink1: '
|
||||
'VL1}\n - {virtualLink2: VL2}\n type: tosca.node'
|
||||
's.nfv.VNF1\n VNF2: {type: tosca.nodes.nfv.VNF2}\ntosca'
|
||||
'_definitions_version: tosca_simple_profile_for_nfv_1_0_0'
|
||||
'\n'}
|
||||
nsd_template = ns_db.NSD(
|
||||
id='be18005d-5656-4d81-b499-6af4d4d8437f',
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
name='dummy_NSD',
|
||||
vnfds={'tosca.nodes.nfv.VNF1': 'vnf1',
|
||||
'tosca.nodes.nfv.VNF2': 'vnf2'},
|
||||
description='dummy_nsd_description',
|
||||
deleted_at=datetime.min,
|
||||
template_source='inline')
|
||||
session.add(nsd_template)
|
||||
for (key, value) in attributes.items():
|
||||
attribute_db = ns_db.NSDAttribute(
|
||||
id=str(uuid.uuid4()),
|
||||
nsd_id='be18005d-5656-4d81-b499-6af4d4d8437f',
|
||||
key=key,
|
||||
value=value)
|
||||
session.add(attribute_db)
|
||||
session.flush()
|
||||
return nsd_template
|
||||
|
||||
def _insert_dummy_ns(self):
|
||||
session = self.context.session
|
||||
ns = ns_db.NS(
|
||||
id='ba6bf017-f6f7-45f1-a280-57b073bf78ea',
|
||||
name='fake_ns',
|
||||
name='dummy_ns',
|
||||
tenant_id='ad7ebc56538745a08ef7c5e97f8bd437',
|
||||
status='ACTIVE',
|
||||
nsd_id='eb094833-995e-49f0-a047-dfb56aaf7c4e',
|
||||
vim_id='6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
description='fake_ns_description',
|
||||
description='dummy_ns_description',
|
||||
deleted_at=datetime.min)
|
||||
session.add(ns)
|
||||
session.flush()
|
||||
@@ -720,7 +808,24 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual('dummy_NSD', result['name'])
|
||||
self.assertIn('id', result)
|
||||
self.assertEqual('dummy nsd description', result['description'])
|
||||
self.assertEqual('dummy_NSD', result['name'])
|
||||
self.assertEqual('onboarded', result['template_source'])
|
||||
self.assertEqual('8819a1542a5948b68f94d4be0fd50496',
|
||||
result['tenant_id'])
|
||||
self.assertIn('attributes', result)
|
||||
self.assertIn('created_at', result)
|
||||
self.assertIn('updated_at', result)
|
||||
|
||||
def test_create_nsd_inline(self):
|
||||
nsd_obj = utils.get_dummy_nsd_obj_inline()
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
result = self.nfvo_plugin.create_nsd(self.context, nsd_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertEqual('dummy_NSD_inline', result['name'])
|
||||
self.assertEqual('inline', result['template_source'])
|
||||
self.assertEqual('8819a1542a5948b68f94d4be0fd50496',
|
||||
result['tenant_id'])
|
||||
self.assertIn('attributes', result)
|
||||
@@ -753,6 +858,38 @@ class TestNfvoPlugin(db_base.SqlTestCase):
|
||||
self.assertIn('status', result)
|
||||
self.assertIn('tenant_id', result)
|
||||
|
||||
@mock.patch('tacker.nfvo.nfvo_plugin.NfvoPlugin.create_nsd')
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, 'get_auth_dict')
|
||||
@mock.patch.object(vim_client.VimClient, 'get_vim')
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, '_get_by_name')
|
||||
def test_create_ns_inline(self, mock_get_by_name, mock_get_vimi,
|
||||
mock_auth_dict, mock_create_nsd):
|
||||
self._insert_dummy_ns_template_inline()
|
||||
self._insert_dummy_vim()
|
||||
mock_auth_dict.return_value = {
|
||||
'auth_url': 'http://127.0.0.1',
|
||||
'token': 'DummyToken',
|
||||
'project_domain_name': 'dummy_domain',
|
||||
'project_name': 'dummy_project'
|
||||
}
|
||||
with patch.object(TackerManager, 'get_service_plugins') as \
|
||||
mock_plugins:
|
||||
mock_plugins.return_value = {'VNFM': FakeVNFMPlugin()}
|
||||
mock_get_by_name.return_value = get_by_name()
|
||||
mock_create_nsd.return_value = {'id':
|
||||
'be18005d-5656-4d81-b499-6af4d4d8437f'}
|
||||
|
||||
ns_obj = utils.get_dummy_ns_obj_inline()
|
||||
result = self.nfvo_plugin.create_ns(self.context, ns_obj)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertIn('id', result)
|
||||
self.assertEqual(ns_obj['ns']['nsd_id'], result['nsd_id'])
|
||||
self.assertEqual(ns_obj['ns']['name'], result['name'])
|
||||
self.assertEqual('dummy_ns_inline', result['name'])
|
||||
self.assertIn('status', result)
|
||||
self.assertIn('tenant_id', result)
|
||||
mock_create_nsd.assert_called_once_with(mock.ANY, mock.ANY)
|
||||
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, 'get_auth_dict')
|
||||
@mock.patch.object(vim_client.VimClient, 'get_vim')
|
||||
@mock.patch.object(nfvo_plugin.NfvoPlugin, '_get_by_name')
|
||||
|
||||
Reference in New Issue
Block a user