Update creating directly VNFFG and NS from descriptor template.
Currently, Tacker only support creating VNFFG and NS from VNFFG descriptor and NS descriptor. This patch will support creating directy VNFFG and NS from template file without initiating VNFFG and NS descriptors before. Change-Id: I4e8ec8405a291300aa6749cf814ad582786c285d Closes-bug: #1681032
This commit is contained in:
parent
a214de6629
commit
d62364cbff
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.
|
@ -566,8 +566,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._i18n import _
|
||||
@ -73,6 +74,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"""
|
||||
@ -192,8 +196,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)
|
||||
@ -220,15 +224,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'),
|
||||
@ -241,6 +247,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)
|
||||
@ -288,7 +297,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']]
|
||||
@ -324,7 +333,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']
|
||||
|
||||
@ -362,9 +371,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,
|
||||
@ -400,7 +409,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)
|
||||
|
||||
@ -663,7 +672,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
|
||||
@ -904,9 +913,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:
|
||||