From 8af1e2e08bc5390fce5cd47ef8e9dee7da0e55ff Mon Sep 17 00:00:00 2001 From: zhiyuan_cai Date: Thu, 13 Jul 2017 14:46:56 +0800 Subject: [PATCH] Add service function chaining smoke test 1. What is the problem Smoke test engine has been implemented[1] and tests for single north-south gateway topology and multiple north-south gateway topology have been added. But we still lack test for service function chain. 2. What is the solution for the problem Define service function chain related test using YAML file. 3. What features need to be implemented to the Tricircle to realize the solution N/A [1] https://review.openstack.org/#/c/477500/ Implements: blueprint smoke-test-engine Change-Id: I02a9bc8a6c7cebe166a633764e424e3812a9a042 --- devstack/plugin.sh | 12 +- devstack/settings | 1 + tricircle/tempestplugin/gate_hook.sh | 8 + tricircle/tempestplugin/sfc_test.yaml | 556 ++++++++++++++++++ tricircle/tempestplugin/smoke_test.sh | 8 + tricircle/tempestplugin/task_runner.py | 15 +- tricircle/tests/network_sdk/v2/_proxy.py | 57 ++ .../tests/network_sdk/v2/flow_classifier.py | 44 ++ tricircle/tests/network_sdk/v2/port_chain.py | 37 ++ tricircle/tests/network_sdk/v2/port_pair.py | 37 ++ .../tests/network_sdk/v2/port_pair_group.py | 36 ++ 11 files changed, 806 insertions(+), 5 deletions(-) create mode 100644 tricircle/tempestplugin/sfc_test.yaml create mode 100644 tricircle/tests/network_sdk/v2/flow_classifier.py create mode 100644 tricircle/tests/network_sdk/v2/port_chain.py create mode 100644 tricircle/tests/network_sdk/v2/port_pair.py create mode 100644 tricircle/tests/network_sdk/v2/port_pair_group.py diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 9e0ee594..0d34c414 100644 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -282,8 +282,18 @@ function start_central_neutron_server { iniset $NEUTRON_CONF.$server_index client auto_refresh_endpoint True iniset $NEUTRON_CONF.$server_index client top_region_name $CENTRAL_REGION_NAME + local service_plugins='' if [ "$TRICIRCLE_ENABLE_TRUNK" == "True" ]; then - iniset $NEUTRON_CONF.$server_index DEFAULT service_plugins "tricircle.network.central_trunk_plugin.TricircleTrunkPlugin" + service_plugins+=",tricircle.network.central_trunk_plugin.TricircleTrunkPlugin" + fi + if [ "$TRICIRCLE_ENABLE_SFC" == "True" ]; then + service_plugins+=",networking_sfc.services.flowclassifier.plugin.FlowClassifierPlugin,tricircle.network.central_sfc_plugin.TricircleSfcPlugin" + iniset $NEUTRON_CONF.$server_index sfc drivers tricircle_sfc + iniset $NEUTRON_CONF.$server_index flowclassifier drivers tricircle_fc + fi + if [ -n service_plugins ]; then + service_plugins=$(echo $service_plugins| sed 's/^,//') + iniset $NEUTRON_CONF.$server_index DEFAULT service_plugins "$service_plugins" fi local type_drivers='' diff --git a/devstack/settings b/devstack/settings index 365ee4dc..cc2adba3 100644 --- a/devstack/settings +++ b/devstack/settings @@ -12,6 +12,7 @@ TRICIRCLE_DEPLOY_WITH_CELL=${TRICIRCLE_DEPLOY_WITH_CELL:-False} # extensions working with tricircle TRICIRCLE_ENABLE_TRUNK=${TRICIRCLE_ENABLE_TRUNK:-False} +TRICIRCLE_ENABLE_SFC=${TRICIRCLE_ENABLE_SFC:-False} # these default settings are used for devstack based gate/check jobs TRICIRCLE_DEFAULT_VLAN_BRIDGE=${TRICIRCLE_DEFAULT_VLAN_BRIDGE:-br-vlan} diff --git a/tricircle/tempestplugin/gate_hook.sh b/tricircle/tempestplugin/gate_hook.sh index bb7ce5ca..e7baa129 100755 --- a/tricircle/tempestplugin/gate_hook.sh +++ b/tricircle/tempestplugin/gate_hook.sh @@ -26,6 +26,7 @@ GATE_DEST=$BASE/new function _setup_tricircle_multinode { + export PROJECTS="openstack/networking-sfc $PROJECTS" PRIMARY_NODE_IP=$(cat /etc/nodepool/primary_node_private) SUBNODE_IP=$(head -n1 /etc/nodepool/sub_nodes_private) @@ -39,11 +40,14 @@ function _setup_tricircle_multinode { export OVERRIDE_ENABLED_SERVICES+="dstat,peakmem_tracker,rabbit,mysql" ENABLE_TRICIRCLE="enable_plugin tricircle https://git.openstack.org/openstack/tricircle/" + ENABLE_SFC="enable_plugin networking-sfc https://git.openstack.org/openstack/networking-sfc/" # Configure primary node export DEVSTACK_LOCAL_CONFIG="$ENABLE_TRICIRCLE" + export DEVSTACK_LOCAL_CONFIG+=$'\n'"$ENABLE_SFC" export DEVSTACK_LOCAL_CONFIG+=$'\n'"TRICIRCLE_START_SERVICES=True" export DEVSTACK_LOCAL_CONFIG+=$'\n'"TRICIRCLE_ENABLE_TRUNK=True" + export DEVSTACK_LOCAL_CONFIG+=$'\n'"TRICIRCLE_ENABLE_SFC=True" export DEVSTACK_LOCAL_CONFIG+=$'\n'"REGION_NAME=RegionOne" export DEVSTACK_LOCAL_CONFIG+=$'\n'"HOST_IP=$PRIMARY_NODE_IP" @@ -52,6 +56,8 @@ function _setup_tricircle_multinode { ML2_CONFIG+=$'\n'"[ml2]" ML2_CONFIG+=$'\n'"mechanism_drivers = openvswitch,linuxbridge,l2population" ML2_CONFIG+=$'\n'"[agent]" + ML2_CONFIG+=$'\n'"extensions=sfc" + ML2_CONFIG+=$'\n'"arp_responder=True" ML2_CONFIG+=$'\n'"tunnel_types=vxlan" ML2_CONFIG+=$'\n'"l2_population=True" @@ -59,8 +65,10 @@ function _setup_tricircle_multinode { # Configure sub-node export DEVSTACK_SUBNODE_CONFIG="$ENABLE_TRICIRCLE" + export DEVSTACK_SUBNODE_CONFIG+=$'\n'"$ENABLE_SFC" export DEVSTACK_SUBNODE_CONFIG+=$'\n'"TRICIRCLE_START_SERVICES=False" export DEVSTACK_SUBNODE_CONFIG+=$'\n'"TRICIRCLE_ENABLE_TRUNK=True" + export DEVSTACK_SUBNODE_CONFIG+=$'\n'"TRICIRCLE_ENABLE_SFC=True" export DEVSTACK_SUBNODE_CONFIG+=$'\n'"REGION_NAME=RegionTwo" export DEVSTACK_SUBNODE_CONFIG+=$'\n'"HOST_IP=$SUBNODE_IP" export DEVSTACK_SUBNODE_CONFIG+=$'\n'"KEYSTONE_REGION_NAME=RegionOne" diff --git a/tricircle/tempestplugin/sfc_test.yaml b/tricircle/tempestplugin/sfc_test.yaml new file mode 100644 index 00000000..72f5bedd --- /dev/null +++ b/tricircle/tempestplugin/sfc_test.yaml @@ -0,0 +1,556 @@ +- task_set_id: preparation + tasks: + - task_id: image1 + type: image + region: region1 + query: + get_one: true + - task_id: image2 + type: image + region: region2 + query: + get_one: true + - task_id: net1 + type: network + region: central + params: + name: net1 + provider_network_type: vxlan + - task_id: subnet1 + type: subnet + region: central + depend: [net1] + params: + name: subnet1 + ip_version: 4 + cidr: 10.0.1.0/24 + network_id: net1@id + - task_id: p1 + type: port + region: central + depend: + - net1 + - subnet1 + params: + name: p1 + network_id: net1@id + - task_id: p2 + type: port + region: central + depend: + - net1 + - subnet1 + params: + name: p2 + network_id: net1@id + - task_id: p3 + type: port + region: central + depend: + - net1 + - subnet1 + params: + name: p3 + network_id: net1@id + - task_id: p4 + type: port + region: central + depend: + - net1 + - subnet1 + params: + name: p4 + network_id: net1@id + - task_id: p5 + type: port + region: central + depend: + - net1 + - subnet1 + params: + name: p5 + network_id: net1@id + - task_id: p6 + type: port + region: central + depend: + - net1 + - subnet1 + params: + name: p6 + network_id: net1@id + - task_id: vm_sfc1 + region: region1 + type: server + depend: + - p2 + - p3 + - image1 + params: + flavor_id: 1 + image_id: image1@id + name: vm_sfc1 + networks: + - port: p2@id + - port: p3@id + - task_id: vm_sfc2 + region: region2 + type: server + depend: + - p4 + - p5 + - image2 + params: + flavor_id: 1 + image_id: image2@id + name: vm_sfc2 + networks: + - port: p4@id + - port: p5@id + - task_id: vm_src + region: region1 + type: server + depend: + - p1 + - image1 + params: + flavor_id: 1 + image_id: image1@id + name: vm_src + networks: + - port: p1@id + - task_id: vm_dst + region: region2 + type: server + depend: + - p6 + - image2 + params: + flavor_id: 1 + image_id: image2@id + name: vm_dst + networks: + - port: p6@id + - task_id: wait-servers1 + region: region1 + type: server + depend: + - vm_src + - vm_sfc1 + validate: + predicate: any + retries: 10 + condition: + - status: ACTIVE + name: vm_src + - status: ACTIVE + name: vm_sfc1 + - task_id: wait-servers2 + region: region2 + type: server + depend: + - wait-servers1 + - vm_dst + - vm_sfc2 + validate: + predicate: any + retries: 10 + condition: + - status: ACTIVE + name: vm_dst + - status: ACTIVE + name: vm_sfc2 + - task_id: pp1 + region: central + type: port_pair + depend: + - vm_sfc1 + - p2 + - p3 + - wait-servers2 + params: + name: pp1 + ingress: p2@id + egress: p3@id + - task_id: pp2 + region: central + type: port_pair + depend: + - vm_sfc2 + - p4 + - p5 + - wait-servers2 + params: + name: pp2 + ingress: p4@id + egress: p5@id + - task_id: ppg1 + region: central + type: port_pair_group + depend: [pp1] + params: + name: ppg1 + port_pairs: [pp1@id] + - task_id: ppg2 + region: central + type: port_pair_group + depend: [pp2] + params: + name: ppg2 + port_pairs: [pp2@id] + - task_id: fc + region: central + type: flow_classifier + depend: [p1] + params: + name: fc + logical_source_port: p1@id + source_ip_prefix: 10.0.1.0/24 + - task_id: pc + region: central + type: port_chain + depend: + - ppg1 + - ppg2 + - fc + params: + name: pc + flow_classifiers: [fc@id] + port_pair_groups: + - ppg1@id + - ppg2@id +- task_set_id: wait-for-job + tasks: + - task_id: check-job + region: central + type: job + validate: + predicate: all + retries: 10 + condition: + - status: SUCCESS +- task_set_id: check + depend: [preparation] + tasks: + - task_id: pp1-1 + region: region1 + type: port_pair + query: + get_one: true + params: + name: pp1 + - task_id: pp1-2 + region: region2 + type: port_pair + query: + get_one: true + params: + name: pp1 + - task_id: pp2-1 + region: region1 + type: port_pair + query: + get_one: true + params: + name: pp2 + - task_id: pp2-2 + region: region2 + type: port_pair + query: + get_one: true + params: + name: pp2 + - task_id: ppg1-1 + region: region1 + type: port_pair_group + query: + get_one: true + params: + name: ppg1 + - task_id: ppg1-2 + region: region2 + type: port_pair_group + query: + get_one: true + params: + name: ppg1 + - task_id: ppg2-1 + region: region1 + type: port_pair_group + query: + get_one: true + params: + name: ppg2 + - task_id: ppg2-2 + region: region2 + type: port_pair_group + query: + get_one: true + params: + name: ppg2 + - task_id: fc-1 + region: region1 + type: flow_classifier + query: + get_one: true + params: + name: fc + - task_id: fc-2 + region: region2 + type: flow_classifier + query: + get_one: true + params: + name: fc + - task_id: check-pp-1 + region: region1 + type: port_pair + validate: + predicate: any + condition: + - ingress: preparation@p2@id + egress: preparation@p3@id + name: pp1 + - ingress: preparation@p4@id + egress: preparation@p5@id + name: pp2 + - task_id: check-pp-2 + region: region2 + type: port_pair + validate: + predicate: any + condition: + - ingress: preparation@p2@id + egress: preparation@p3@id + name: pp1 + - ingress: preparation@p4@id + egress: preparation@p5@id + name: pp2 + - task_id: check-ppg-1 + region: region1 + type: port_pair_group + depend: + - pp1-1 + - pp2-1 + validate: + predicate: any + condition: + - name: ppg1 + port_pairs: [pp1-1@id] + - name: ppg2 + port_pairs: [pp2-1@id] + - task_id: check-ppg-2 + region: region2 + type: port_pair_group + depend: + - pp1-2 + - pp2-2 + validate: + predicate: any + condition: + - name: ppg1 + port_pairs: [pp1-2@id] + - name: ppg2 + port_pairs: [pp2-2@id] + - task_id: check-pc-1 + region: region1 + type: port_chain + depend: + - ppg1-1 + - ppg2-1 + - fc-1 + validate: + predicate: any + condition: + - name: pc + port_pair_groups: + - ppg1-1@id + - ppg2-1@id + flow_classifiers: [fc-1@id] + - task_id: check-pc-2 + region: region2 + type: port_chain + depend: + - ppg1-2 + - ppg2-2 + - fc-2 + validate: + predicate: any + condition: + - name: pc + port_pair_groups: + - ppg1-2@id + - ppg2-2@id + flow_classifiers: [fc-2@id] +- task_set_id: clean + depend: [preparation] + tasks: + - task_id: delete-pc + region: central + type: port_chain + action: + target: preparation@pc@id + method: delete + - task_id: delete-fc + region: central + type: flow_classifier + depend: [delete-pc] + action: + target: preparation@fc@id + method: delete + - task_id: delete-ppg1 + region: central + type: port_pair_group + depend: [delete-pc] + action: + target: preparation@ppg1@id + method: delete + - task_id: delete-ppg2 + region: central + type: port_pair_group + depend: [delete-pc] + action: + target: preparation@ppg2@id + method: delete + - task_id: delete-pp1 + region: central + type: port_pair + depend: [delete-ppg1] + action: + target: preparation@pp1@id + method: delete + - task_id: delete-pp2 + region: central + type: port_pair + depend: [delete-ppg2] + action: + target: preparation@pp2@id + method: delete + - task_id: delete-vm-src + region: region1 + type: server + action: + target: preparation@vm_src@id + method: delete + - task_id: delete-vm-sfc1 + region: region1 + type: server + depend: [delete-pp1] + action: + target: preparation@vm_sfc1@id + method: delete + - task_id: delete-vm-dst + region: region2 + type: server + action: + target: preparation@vm_dst@id + method: delete + - task_id: delete-vm-sfc2 + region: region2 + type: server + depend: [delete-pp2] + action: + target: preparation@vm_sfc2@id + method: delete +- task_set_id: wait-server-delete + tasks: + - task_id: check-no-servers-1 + region: region1 + type: server + validate: + retries: 10 + predicate: all + condition: + - name: invalid-name + - task_id: check-no-servers-2 + region: region2 + type: server + validate: + retries: 10 + predicate: all + condition: + - name: invalid-name +- task_set_id: clean-cont + depend: [preparation] + tasks: + - task_id: delete-p1 + region: central + type: port + action: + target: preparation@p1@id + method: delete + - task_id: delete-p2 + region: central + type: port + action: + target: preparation@p2@id + method: delete + - task_id: delete-p3 + region: central + type: port + action: + target: preparation@p3@id + method: delete + - task_id: delete-p4 + region: central + type: port + action: + target: preparation@p4@id + method: delete + - task_id: delete-p5 + region: central + type: port + action: + target: preparation@p5@id + method: delete + - task_id: delete-p6 + region: central + type: port + action: + target: preparation@p6@id + method: delete + - task_id: delete-subnet + region: central + depend: + - delete-p1 + - delete-p2 + - delete-p3 + - delete-p4 + - delete-p5 + - delete-p6 + type: subnet + action: + target: preparation@subnet1@id + method: delete + retries: 3 + - task_id: delete-net + region: central + depend: [delete-subnet] + type: network + action: + target: preparation@net1@id + method: delete +- task_set_id: clean-check + tasks: + - task_id: check-no-networks1 + region: region1 + type: network + validate: + predicate: all + condition: + - name: invalid-name + - task_id: check-no-networks2 + region: region2 + type: network + validate: + predicate: all + condition: + - name: invalid-name + - task_id: check-jobs + region: central + type: job + validate: + predicate: all + retries: 10 + condition: + - status: SUCCESS diff --git a/tricircle/tempestplugin/smoke_test.sh b/tricircle/tempestplugin/smoke_test.sh index e2bab5cb..7a817fde 100644 --- a/tricircle/tempestplugin/smoke_test.sh +++ b/tricircle/tempestplugin/smoke_test.sh @@ -5,15 +5,23 @@ DEVSTACK_DIR=$DEST/devstack source $DEVSTACK_DIR/openrc admin admin unset OS_REGION_NAME +echo "Start to run single gateway topology test" python run_yaml_test.py single_gw_topology_test.yaml "$OS_AUTH_URL" "$OS_TENANT_NAME" "$OS_USERNAME" "$OS_PASSWORD" if [ $? != 0 ]; then die $LINENO "Smoke test fails, error in single gateway topology test" fi +echo "Start to run multi gateway topology test" python run_yaml_test.py multi_gw_topology_test.yaml "$OS_AUTH_URL" "$OS_TENANT_NAME" "$OS_USERNAME" "$OS_PASSWORD" if [ $? != 0 ]; then die $LINENO "Smoke test fails, error in multi gateway topology test" fi +echo "Start to run trunk test" python run_yaml_test.py trunk_test.yaml "$OS_AUTH_URL" "$OS_TENANT_NAME" "$OS_USERNAME" "$OS_PASSWORD" if [ $? != 0 ]; then die $LINENO "Smoke test fails, error in trunk test" fi +echo "Start to run service function chain test" +python run_yaml_test.py sfc_test.yaml "$OS_AUTH_URL" "$OS_TENANT_NAME" "$OS_USERNAME" "$OS_PASSWORD" +if [ $? != 0 ]; then + die $LINENO "Smoke test fails, error in service function chain test" +fi diff --git a/tricircle/tempestplugin/task_runner.py b/tricircle/tempestplugin/task_runner.py index 86affccb..cd39310c 100644 --- a/tricircle/tempestplugin/task_runner.py +++ b/tricircle/tempestplugin/task_runner.py @@ -66,7 +66,8 @@ class DummyRunner(object): return [] def validate(self, region, _type, predicate, conditions, params): - pass + msg = 'validate %s, conditions: %s' % (_type, conditions) + LOG.info(msg) class SDKRunner(object): @@ -74,7 +75,9 @@ class SDKRunner(object): 'region1': 'RegionOne', 'region2': 'RegionTwo'} serv_reslist_map = { - 'network_sdk': ['network', 'subnet', 'port', 'router', 'fip', 'trunk'], + 'network_sdk': ['network', 'subnet', 'port', 'router', 'fip', 'trunk', + 'flow_classifier', 'port_pair', 'port_pair_group', + 'port_chain'], 'compute': ['server'], 'image': ['image'], 'tricircle_sdk': ['job']} @@ -190,12 +193,14 @@ class SDKRunner(object): for condition in conditions: if not validate_any_condition(results, condition): raise Exception( - 'Validation fail, acutal results: %s' % results) + 'Validation fail, acutal results: %s, ' + 'expected results: %s' % (results, condition)) elif predicate == 'all': for condition in conditions: if not validate_all_condition(results, condition): raise Exception( - 'Validation fail, acutal results: %s' % results) + 'Validation fail, acutal results: %s, ' + 'expected results: %s' % (results, condition)) class RunnerEngine(object): @@ -246,6 +251,8 @@ class RunnerEngine(object): requires = [] if 'params' in task: collect_require_from_dict(requires, task['params']) + if 'validate' in task: + collect_require_from_dict(requires, task['validate']) if 'action' in task: requires.append(task['action']['target']) depend = task.get('depend', []) diff --git a/tricircle/tests/network_sdk/v2/_proxy.py b/tricircle/tests/network_sdk/v2/_proxy.py index d3a8515a..4e5fd9ee 100644 --- a/tricircle/tests/network_sdk/v2/_proxy.py +++ b/tricircle/tests/network_sdk/v2/_proxy.py @@ -14,10 +14,15 @@ from openstack.network.v2 import _proxy +import tricircle.tests.network_sdk.v2.flow_classifier as _fc +import tricircle.tests.network_sdk.v2.port_chain as _pc +import tricircle.tests.network_sdk.v2.port_pair as _pp +import tricircle.tests.network_sdk.v2.port_pair_group as _ppg import tricircle.tests.network_sdk.v2.trunk as _trunk class Proxy(_proxy.Proxy): + # trunk def create_trunk(self, **attrs): return self._create(_trunk.Trunk, **attrs) @@ -39,3 +44,55 @@ class Proxy(_proxy.Proxy): trunk = self._get_resource(_trunk.Trunk, trunk) body = {'sub_ports': subports} return trunk.remove_subports(self._session, **body) + + # port pair + def create_port_pair(self, **attrs): + return self._create(_pp.PortPair, **attrs) + + def delete_port_pair(self, pp, ignore_missing=True): + self._delete(_pp.PortPair, pp, ignore_missing=ignore_missing) + + def update_port_pair(self, pp, **attrs): + return self._update(_pp.PortPair, pp, **attrs) + + def port_pairs(self, **query): + return self._list(_pp.PortPair, pagination=False, **query) + + # port pair group + def create_port_pair_group(self, **attrs): + return self._create(_ppg.PortPairGroup, **attrs) + + def delete_port_pair_group(self, ppg, ignore_missing=True): + self._delete(_ppg.PortPairGroup, ppg, ignore_missing=ignore_missing) + + def update_port_pair_group(self, ppg, **attrs): + return self._update(_ppg.PortPairGroup, ppg, **attrs) + + def port_pair_groups(self, **query): + return self._list(_ppg.PortPairGroup, pagination=False, **query) + + # port chain + def create_port_chain(self, **attrs): + return self._create(_pc.PortChain, **attrs) + + def delete_port_chain(self, pc, ignore_missing=True): + self._delete(_pc.PortChain, pc, ignore_missing=ignore_missing) + + def update_port_chain(self, pc, **attrs): + return self._update(_pc.PortChain, pc, **attrs) + + def port_chains(self, **query): + return self._list(_pc.PortChain, pagination=False, **query) + + # flow classifier + def create_flow_classifier(self, **attrs): + return self._create(_fc.FlowClassifier, **attrs) + + def delete_flow_classifier(self, fc, ignore_missing=True): + self._delete(_fc.FlowClassifier, fc, ignore_missing=ignore_missing) + + def update_flow_classifier(self, fc, **attrs): + return self._update(_fc.FlowClassifier, fc, **attrs) + + def flow_classifiers(self, **query): + return self._list(_fc.FlowClassifier, pagination=False, **query) diff --git a/tricircle/tests/network_sdk/v2/flow_classifier.py b/tricircle/tests/network_sdk/v2/flow_classifier.py new file mode 100644 index 00000000..7005b31c --- /dev/null +++ b/tricircle/tests/network_sdk/v2/flow_classifier.py @@ -0,0 +1,44 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from openstack import resource2 + +from tricircle.tests.network_sdk import network_service + + +class FlowClassifier(resource2.Resource): + resource_key = 'flow_classifier' + resources_key = 'flow_classifiers' + base_path = '/sfc/flow_classifiers' + service = network_service.NetworkService() + + allow_create = True + allow_get = True + allow_update = True + allow_delete = True + allow_list = True + + _query_mapping = resource2.QueryParameters('name') + + name = resource2.Body('name') + description = resource2.Body('description') + ethertype = resource2.Body('ingress') + protocol = resource2.Body('protocol') + source_port_range_min = resource2.Body('source_port_range_min') + source_port_range_max = resource2.Body('source_port_range_max') + destination_port_range_min = resource2.Body('destination_port_range_min') + destination_port_range_max = resource2.Body('destination_port_range_max') + source_ip_prefix = resource2.Body('source_ip_prefix') + destination_ip_prefix = resource2.Body('destination_ip_prefix') + logical_source_port = resource2.Body('logical_source_port') + logical_destination_port = resource2.Body('logical_destination_port') + l7_parameters = resource2.Body('l7_parameters', type=dict) diff --git a/tricircle/tests/network_sdk/v2/port_chain.py b/tricircle/tests/network_sdk/v2/port_chain.py new file mode 100644 index 00000000..a898ba73 --- /dev/null +++ b/tricircle/tests/network_sdk/v2/port_chain.py @@ -0,0 +1,37 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from openstack import resource2 + +from tricircle.tests.network_sdk import network_service + + +class PortChain(resource2.Resource): + resource_key = 'port_chain' + resources_key = 'port_chains' + base_path = '/sfc/port_chains' + service = network_service.NetworkService() + + allow_create = True + allow_get = True + allow_update = True + allow_delete = True + allow_list = True + + _query_mapping = resource2.QueryParameters('name') + + name = resource2.Body('name') + description = resource2.Body('description') + port_pair_groups = resource2.Body('port_pair_groups', type=list) + flow_classifiers = resource2.Body('flow_classifiers', type=list) + chain_parameters = resource2.Body('chain_parameters', type=dict) + chain_id = resource2.Body('chain_id') diff --git a/tricircle/tests/network_sdk/v2/port_pair.py b/tricircle/tests/network_sdk/v2/port_pair.py new file mode 100644 index 00000000..5fed625e --- /dev/null +++ b/tricircle/tests/network_sdk/v2/port_pair.py @@ -0,0 +1,37 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from openstack import resource2 + +from tricircle.tests.network_sdk import network_service + + +class PortPair(resource2.Resource): + resource_key = 'port_pair' + resources_key = 'port_pairs' + base_path = '/sfc/port_pairs' + service = network_service.NetworkService() + + allow_create = True + allow_get = True + allow_update = True + allow_delete = True + allow_list = True + + _query_mapping = resource2.QueryParameters('name') + + name = resource2.Body('name') + description = resource2.Body('description') + ingress = resource2.Body('ingress') + egress = resource2.Body('egress') + service_function_parameters = resource2.Body('service_function_parameters', + type=dict) diff --git a/tricircle/tests/network_sdk/v2/port_pair_group.py b/tricircle/tests/network_sdk/v2/port_pair_group.py new file mode 100644 index 00000000..18d17dcc --- /dev/null +++ b/tricircle/tests/network_sdk/v2/port_pair_group.py @@ -0,0 +1,36 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from openstack import resource2 + +from tricircle.tests.network_sdk import network_service + + +class PortPairGroup(resource2.Resource): + resource_key = 'port_pair_group' + resources_key = 'port_pair_groups' + base_path = '/sfc/port_pair_groups' + service = network_service.NetworkService() + + allow_create = True + allow_get = True + allow_update = True + allow_delete = True + allow_list = True + + _query_mapping = resource2.QueryParameters('name') + + name = resource2.Body('name') + description = resource2.Body('description') + port_pairs = resource2.Body('port_pairs', type=list) + port_pair_group_parameters = resource2.Body('port_pair_group_parameters', + type=dict)