From: Isaku Yamahata Date: Wed, 8 Mar 2017 19:25:42 +0000 (-0800) Subject: tapaas: tapaas support X-Git-Tag: release/oxygen~21 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=16992950401973c54f4ac24c7935fa6b7d189ef0;p=neutron.git tapaas: tapaas support Added Tap-As-A-Service implementation in Neutron. Added Northbound-api, spi and transcriber Also added postman script to test the implementation. Updated the copyright dates and names Added unit tests and e2etests Change-Id: I2febd008cfa86e70557123e82a1621eaa80e832c Signed-off-by: Isaku Yamahata Signed-off-by: Kiran Kamineni --- diff --git a/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronTapFlowTests.java b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronTapFlowTests.java new file mode 100644 index 000000000..324040c33 --- /dev/null +++ b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronTapFlowTests.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2017 Intel, Corp. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.e2etest; + +public class NeutronTapFlowTests { + String base; + + public NeutronTapFlowTests(String base) { + this.base = base; + } + + public void tap_flow_collection_get_test() { + String url = base + "/tap/flows"; + ITNeutronE2E.test_fetch(url, "Tap Flow collection GET failed"); + } + + public String singleton_tap_flow_create_test() { + String url = base + "/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546/flows"; + String content = "{\"tap_flow\": {\"id\": \"f6220bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\"," + + "\"name\": \"tap-flow-test\"," + + "\"tap_service_id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"source_port\": \"411d75c3-4da8-4267-8aed-6dbb19a3dcfe\"," + + "\"direction\": \"BOTH\" }}"; + ITNeutronE2E.test_create(url, content, "Tap Flow Singleton POST Failed"); + return content; + } + + public void singleton_tap_flow_get_with_query_item_test(String createJsonString) { + String url = base + "/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546"; + ITNeutronE2E.test_fetch_with_one_query_item(url, createJsonString, "flows"); + } + + public void tap_flow_modify_test() { + String url = base + "/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546" + + "/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546"; + String content = "{\"tap-flow\": {\"id\": \"f6220bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\"," + + "\"name\": \"tap-flow-test2\"," + + "\"tap_service_id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"source_port\": \"611d75c3-4da8-4267-8aed-6dbb19a3dcfe\"," + + "\"direction\": \"IN\" }}"; + ITNeutronE2E.test_modify(url, content, "Tap Flow Singleton PUT failed"); + } + + public void tap_flow_element_get_test() { + String url = base + "/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546" + + "/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546"; + ITNeutronE2E.test_fetch(url, true, "Tap Flow Element Get failed"); + } + + public void tap_flow_element_get_with_query_test() { + String url = base + "/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546" + + "/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546" + + "?fields=tenant_id&fields=id&fields=name&fields=tap_service_id" + + "?fields=source_port&fields=direction" + + "&fields=limits&fields=marker&fields=page_reverse"; + ITNeutronE2E.test_fetch(url, true, "Tap Flow Element Get with Query Failed"); + } + + public void tap_flow_delete_test() { + String url = base + "/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546" + + "/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546"; + ITNeutronE2E.test_delete(url, "Tap Flow Delete Failed"); + } + + public void tap_flow_element_negative_get_test() { + String url = base + "/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546" + + "/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546"; + ITNeutronE2E.test_fetch(url, false, "Tap Flow Element Negative Get Failed"); + } + + public static void runTests(String base) { + NeutronTapFlowTests tapFlowTester = new NeutronTapFlowTests(base); + String createJsonString = tapFlowTester.singleton_tap_flow_create_test(); + tapFlowTester.singleton_tap_flow_get_with_query_item_test(createJsonString); + tapFlowTester.tap_flow_element_get_test(); + tapFlowTester.tap_flow_element_get_with_query_test(); + tapFlowTester.tap_flow_collection_get_test(); + tapFlowTester.tap_flow_modify_test(); + tapFlowTester.tap_flow_delete_test(); + tapFlowTester.tap_flow_element_negative_get_test(); + } +} diff --git a/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronTapServiceTests.java b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronTapServiceTests.java new file mode 100644 index 000000000..99659898c --- /dev/null +++ b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronTapServiceTests.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 Intel, Corp. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.e2etest; + +public class NeutronTapServiceTests { + String base; + + public NeutronTapServiceTests(String base) { + this.base = base; + } + + public void tap_service_collection_get_test() { + String url = base + "/tap/services"; + ITNeutronE2E.test_fetch(url, "Tap Service collection GET failed"); + } + + public String singleton_tap_service_create_test() { + String url = base + "/tap/services"; + String content = "{\"tap_service\": {\"id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\"," + + "\"name\": \"tap-service-test\"," + + "\"port_id\": \"311d75c3-4da8-4267-8aed-6dbb19a3dcfe\" }}"; + ITNeutronE2E.test_create(url, content, "Tap Service Singleton POST Failed"); + return content; + } + + public void singleton_tap_service_get_with_query_item_test(String createJsonString) { + String url = base + "/tap/services"; + ITNeutronE2E.test_fetch_with_one_query_item(url, createJsonString, "services"); + } + + public void tap_service_modify_test() { + String url = base + "/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546"; + String content = "{\"tap-service\": {\"id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\"," + + "\"name\": \"tap-service-test\"," + + "\"port_id\": \"311d75c3-4da8-4267-8aed-6dbb19a3dcfe\" }}"; + ITNeutronE2E.test_modify(url, content, "Tap Service Singleton PUT failed"); + } + + public void tap_service_element_get_test() { + String url = base + "/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546"; + ITNeutronE2E.test_fetch(url, true, "Tap Service Element Get failed"); + } + + public void tap_service_element_get_with_query_test() { + String url = base + "/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546" + + "?fields=tenant_id&fields=id&fields=name&fields=port_id" + + "&fields=limits&fields=marker&fields=page_reverse"; + ITNeutronE2E.test_fetch(url, true, "Tap Service Element Get with Query Failed"); + } + + public void tap_service_delete_test() { + String url = base + "/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546"; + ITNeutronE2E.test_delete(url, "Tap Service Delete Failed"); + } + + public void tap_service_element_negative_get_test() { + String url = base + "/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546"; + ITNeutronE2E.test_fetch(url, false, "Tap Service Element Negative Get Failed"); + } + + public static void runTests(String base) { + NeutronTapServiceTests tapServiceTester = new NeutronTapServiceTests(base); + String createJsonString = tapServiceTester.singleton_tap_service_create_test(); + tapServiceTester.singleton_tap_service_get_with_query_item_test(createJsonString); + tapServiceTester.tap_service_element_get_test(); + tapServiceTester.tap_service_element_get_with_query_test(); + tapServiceTester.tap_service_collection_get_test(); + tapServiceTester.tap_service_modify_test(); + tapServiceTester.tap_service_delete_test(); + tapServiceTester.tap_service_element_negative_get_test(); + } +} diff --git a/model/src/main/yang/neutron-tapaas.yang b/model/src/main/yang/neutron-tapaas.yang new file mode 100644 index 000000000..55d973071 --- /dev/null +++ b/model/src/main/yang/neutron-tapaas.yang @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2017 Intel Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +module neutron-tapaas { + yang-version 1; + namespace "urn:opendaylight:neutron-tapaas"; + prefix neutron-tapaas; + + import ietf-yang-types { prefix "yang"; } + import neutron-attrs { prefix "attrs"; } + + organization "OpenDaylight Neutron Northbound Project"; + + contact "Neutron Northbound "; + + description " This YANG module defines Openstack Neutron Tap-as-a-Service(Taas) Model. + The model is based on the REST APIs exposed by the trunk service of Neutron version 2. + description of the REST API is located in inside the specification for tap-as-a-service + (https://github.com/openstack/tap-as-a-service/blob/master/specs/mitaka/tap-as-a-service.rst)"; + + revision "2017-10-24" { + description + "OpenStack Neutron Tap as a service - Version 1."; + } + + identity direction-base { + description "Base for defining direction of traffic"; + } + + identity direction-in { + description "Traffic arriving at Source Port"; + base direction-base; + } + + identity direction-out { + description "Traffic leaving Source Port"; + base direction-base; + } + + identity direction-both { + description "Both Directions are mirrored"; + base direction-base; + } + + grouping tap-flow-attributes { + description "Grouping for Tap Flow"; + leaf tap-service-id { + type yang:uuid; + description "UUID of the Tap Service Instance"; + } + leaf source-port { + type yang:uuid; + description "Source port of traffic "; + } + leaf direction { + type identityref { + base "direction-base"; + } + description "Direction of traffic"; + } + } + + grouping tap-service-attributes { + description "Grouping for Tap Service"; + leaf port-id { + type yang:uuid; + description "Destination port for traffic"; + } + container tap-flows { + list tap-flow { + key uuid; + uses attrs:base-attributes; + uses tap-flow-attributes; + description "Tap Flow container"; + } + } + } + + grouping tap-services-attributes { + container tap-services { + list tap-service { + key uuid; + uses attrs:base-attributes; + uses tap-service-attributes; + description "Tap Services Container which includes Tap Flow"; + } + } + container tap-services-status { + config false; + list tap-service-status { + key "tap-service"; + leaf tap-service { + type yang:uuid; + description "UUID of the Tap Service Instance"; + } + leaf status { + type string; + description "Operational parameter to track status"; + } + } + } + } +} diff --git a/model/src/main/yang/neutron.yang b/model/src/main/yang/neutron.yang index 1fc44bbbc..0e9fa50e8 100644 --- a/model/src/main/yang/neutron.yang +++ b/model/src/main/yang/neutron.yang @@ -31,6 +31,7 @@ module neutron { import neutron-sfc-flow-classifier { prefix "sfc-flow-classifier"; } import neutron-sfc { prefix "sfc"; } import neutron-trunks { prefix "trunks"; } + import neutron-tapaas { prefix "tapaas"; } organization "OpenDaylight Neutron Group"; @@ -71,5 +72,6 @@ module neutron { uses sfc-flow-classifier:sfc-flow-classifiers-attributes; uses sfc:sfc-attributes; uses trunks:trunks-attributes; + uses tapaas:tap-services-attributes; } } diff --git a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronTapFlowCRUD.java b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronTapFlowCRUD.java new file mode 100644 index 000000000..849be95b5 --- /dev/null +++ b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronTapFlowCRUD.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2017 Intel Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.spi; + +/** + * This interface defines the methods for CRUD of NB OpenStack Tap Flow objects. + */ + +public interface INeutronTapFlowCRUD extends INeutronCRUD { + /** + * Applications call this interface method to check if a NeutronTapFlow object exists. + * + * @param tapServiceUUID + * UUID of Tap Service + * @param tapFlowUUID + * UUID of Tap Flow + * @return boolean on whether the object was added or not + */ + + boolean tapFlowExists(String tapServiceUUID, String tapFlowUUID); + + /** + * Applications call this interface method to get a NeutronTapFlow object. + * + * @param tapServiceUUID + * UUID of Tap Service + * @param tapFlowUUID + * UUID of Tap Flow + * @return NeutronTapFlow object + */ + + NeutronTapFlow getTapFlow(String tapServiceUUID, String tapFlowUUID); + + /** + * Applications call this interface method to add a NeutronTapFlow object to the + * concurrent map. + * + * @param input + * OpenStackNetwork object + * @return boolean on whether the object was added or not + */ + + boolean addTapFlow(NeutronTapFlow input); + + /** + * Applications call this interface method to update a NeutronTapFlow object to the + * concurrent map. + * + * @param input + * OpenStackNetwork object + * @return boolean on whether the object was added or not + */ + + boolean updateTapFlow(NeutronTapFlow input); + + /** + * Applications call this interface method to delete a NeutronTapFlow object. + * + * @param tapServiceUUID + * UUID of Tap Service + * @param tapFlowUUID + * UUID of Tap Flow + * @return boolean on whether the object was added or not + */ + + boolean deleteTapFlow(String tapServiceUUID, String tapFlowUUID); +} diff --git a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronTapServiceCRUD.java b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronTapServiceCRUD.java new file mode 100644 index 000000000..2b4c2b4d0 --- /dev/null +++ b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronTapServiceCRUD.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2017 Intel Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.spi; + +/** + * This interface defines the methods for CRUD of NB OpenStack Tap Service objects. + */ + +public interface INeutronTapServiceCRUD extends INeutronCRUD { + // Nothing Here. + // This class is defined to use reflection. +} diff --git a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronTapFlow.java b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronTapFlow.java new file mode 100644 index 000000000..e58b8dfaf --- /dev/null +++ b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronTapFlow.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017 Intel Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.spi; + +import java.io.Serializable; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public final class NeutronTapFlow extends NeutronBaseAttributes implements Serializable { + private static final long serialVersionUID = 1L; + + @XmlElement(name = "tap_service_id") + String tapServiceID; + + @XmlElement(name = "direction") + String tapFlowDirection; + + @XmlElement(name = "source_port") + String tapFlowSourcePort; + + public String getTapFlowServiceID() { + return tapServiceID; + } + + public void setTapFlowServiceID(String tapService) { + this.tapServiceID = tapService; + } + + public String getTapFlowDirection() { + return tapFlowDirection; + } + + public void setTapFlowDirection(String direction) { + this.tapFlowDirection = direction; + } + + public String getTapFlowSourcePort() { + return tapFlowSourcePort; + } + + public void setTapFlowSourcePort(String sourcePort) { + this.tapFlowSourcePort = sourcePort; + } + + @Override + protected boolean extractField(String field, NeutronTapFlow ans) { + switch (field) { + case "source_port": + ans.setTapFlowSourcePort(this.getTapFlowSourcePort()); + break; + case "direction": + ans.setTapFlowDirection(this.getTapFlowDirection()); + break; + case "tap_service_id": + ans.setTapFlowServiceID(this.getTapFlowServiceID()); + break; + default: + return super.extractField(field, ans); + } + return true; + } + + @Override + public String toString() { + return "NeutronTapFlow[" + "tapFlowUUID='" + uuid + '\'' + ", tapFlowTenantID='" + tenantID + '\'' + + ", tapFlowName='" + name + '\'' + ", tapFlowServiceID='" + tapServiceID + '\'' + + ", tapFlowSourcePort='" + tapFlowSourcePort + '\'' + + ", tapFlowDirection='" + tapFlowDirection + '\'' + ']'; + } +} diff --git a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronTapService.java b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronTapService.java new file mode 100644 index 000000000..5072ea3f0 --- /dev/null +++ b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronTapService.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017 Intel Corporation. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.spi; + +import java.io.Serializable; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public final class NeutronTapService extends NeutronBaseAttributes implements Serializable { + private static final long serialVersionUID = 1L; + + @XmlElement(name = "port_id") + String tapServicePortID; + + public String getTapServicePortID() { + return tapServicePortID; + } + + public void setTapServicePortID(String port) { + this.tapServicePortID = port; + } + + @Override + protected boolean extractField(String field, NeutronTapService ans) { + switch (field) { + case "port_id": + ans.setTapServicePortID(this.getTapServicePortID()); + break; + default: + return super.extractField(field, ans); + } + return true; + } + + @Override + public String toString() { + return "NeutronTapService[" + "tapServiceUUID='" + uuid + '\'' + ", tapServiceTenantID='" + + tenantID + '\'' + ", tapServiceName='" + name + '\'' + ", tapServicePortID='" + + tapServicePortID + '\'' + ']'; + } +} diff --git a/neutron-spi/src/test/java/org/opendaylight/neutron/spi/NeutronTapFlowJAXBTest.java b/neutron-spi/src/test/java/org/opendaylight/neutron/spi/NeutronTapFlowJAXBTest.java new file mode 100644 index 000000000..c5e5a6742 --- /dev/null +++ b/neutron-spi/src/test/java/org/opendaylight/neutron/spi/NeutronTapFlowJAXBTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 Intel, Corp. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.spi; + +import javax.xml.bind.JAXBException; +import org.junit.Assert; +import org.junit.Test; + +public class NeutronTapFlowJAXBTest { + + private static final String NEUTRON_TAP_FLOW_SOURCE_JSON = "{" + + "\"id\": \"f6220bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\"," + + "\"name\": \"tap-flow-test\"," + + "\"tap_service_id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"source_port\": \"411d75c3-4da8-4267-8aed-6dbb19a3dcfe\"," + + "\"direction\": \"BOTH\" " + "}"; + + @Test + public void test_NeutronTapFlow_JAXB() throws JAXBException { + NeutronTapFlow testObject = new NeutronTapFlow(); + NeutronTapFlow neutronObject = (NeutronTapFlow) JaxbTestHelper.jaxbUnmarshall(testObject, + NEUTRON_TAP_FLOW_SOURCE_JSON); + Assert.assertEquals("NeutronTapFlow JAXB Test 1: Testing id failed", "f6220bbb-35f3-48ab-8eae-69c60aef3546", + neutronObject.getID()); + + Assert.assertEquals("NeutronTapFlow JAXB Test 2: Testing tenant_id failed", + "aa902936679e4ea29bfe1158e3450a13", neutronObject.getTenantID()); + + Assert.assertEquals("NeutronTapFlow JAXB Test 3 : Testing name failed", "tap-flow-test", + neutronObject.getName()); + + Assert.assertEquals("NeutronTapFlow JAXB Test 4 : Testing tap_service_id failed", + "b6440bbb-35f3-48ab-8eae-69c60aef3546", neutronObject.getTapFlowServiceID()); + + Assert.assertEquals("NeutronTapFlow JAXB Test 5 : Testing source_port failed", + "411d75c3-4da8-4267-8aed-6dbb19a3dcfe", neutronObject.getTapFlowSourcePort()); + + Assert.assertEquals("NeutronTapFlow JAXB Test 6: Testing direction failed", + "BOTH", neutronObject.getTapFlowDirection()); + + } +} diff --git a/neutron-spi/src/test/java/org/opendaylight/neutron/spi/NeutronTapServiceJAXBTest.java b/neutron-spi/src/test/java/org/opendaylight/neutron/spi/NeutronTapServiceJAXBTest.java new file mode 100644 index 000000000..77bdb5a70 --- /dev/null +++ b/neutron-spi/src/test/java/org/opendaylight/neutron/spi/NeutronTapServiceJAXBTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 Intel, Corp. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.spi; + +import javax.xml.bind.JAXBException; +import org.junit.Assert; +import org.junit.Test; + +public class NeutronTapServiceJAXBTest { + + private static final String NEUTRON_TAP_SERVICE_SOURCE_JSON = "{" + + "\"id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\"," + + "\"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\"," + + "\"name\": \"tap-service-test\"," + + "\"port_id\": \"311d75c3-4da8-4267-8aed-6dbb19a3dcfe\" " + "}"; + + @Test + public void test_NeutronTapService_JAXB() throws JAXBException { + NeutronTapService testObject = new NeutronTapService(); + NeutronTapService neutronObject = (NeutronTapService) JaxbTestHelper.jaxbUnmarshall(testObject, + NEUTRON_TAP_SERVICE_SOURCE_JSON); + Assert.assertEquals("NeutronTapService JAXB Test 1: Testing id failed", "b6440bbb-35f3-48ab-8eae-69c60aef3546", + neutronObject.getID()); + + Assert.assertEquals("NeutronTapService JAXB Test 2: Testing tenant_id failed", + "aa902936679e4ea29bfe1158e3450a13", neutronObject.getTenantID()); + + Assert.assertEquals("NeutronTapService JAXB Test 3 : Testing name failed", "tap-service-test", + neutronObject.getName()); + + Assert.assertEquals("NeutronTapService JAXB Test 4 : Testing port_id failed", + "311d75c3-4da8-4267-8aed-6dbb19a3dcfe", neutronObject.getTapServicePortID()); + + } +} diff --git a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronNorthboundRSApplication.java b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronNorthboundRSApplication.java index 904e982db..821063b03 100644 --- a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronNorthboundRSApplication.java +++ b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronNorthboundRSApplication.java @@ -57,6 +57,8 @@ public final class NeutronNorthboundRSApplication extends Application { classes.add(NeutronSFCPortChainsNorthbound.class); classes.add(NeutronQosPolicyNorthbound.class); classes.add(NeutronTrunksNorthbound.class); + classes.add(NeutronTapServiceNorthbound.class); + classes.add(NeutronTapFlowNorthbound.class); classes.add(MOXyJsonProvider.class); return classes; diff --git a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapFlowNorthbound.java b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapFlowNorthbound.java new file mode 100644 index 000000000..3bd900b49 --- /dev/null +++ b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapFlowNorthbound.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2017 Intel, Corp. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.northbound.api; + +import java.net.HttpURLConnection; +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.neutron.spi.INeutronTapFlowCRUD; +import org.opendaylight.neutron.spi.NeutronTapFlow; + +@Path("/tap/flows") +public final class NeutronTapFlowNorthbound + extends AbstractNeutronNorthbound { + + private static final String RESOURCE_NAME = "Tap Flow"; + + @Override + protected String getResourceName() { + return RESOURCE_NAME; + } + + /** + * Returns a list of all Tap Flows. + */ + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response listGroups( + // return fields + @QueryParam("fields") List fields, + // OpenStack Tap Flow attributes + @QueryParam("id") String queryTapFlowUUID, + @QueryParam("tenant_id") String queryTapFlowTenantID, + @QueryParam("name") String queryTapFlowName, + @QueryParam("source_port") String queryTapFlowSourcePort, + @QueryParam("tap_service_id") String queryTapServiceID, + @QueryParam("direction") String queryTapFlowDirection, + // pagination + @QueryParam("limit") String limit, + @QueryParam("marker") String marker, + @QueryParam("page_reverse") String pageReverse) { + + INeutronTapFlowCRUD tapFlowInterface = getNeutronCRUD(); + List ans = new ArrayList<>(); + for (NeutronTapFlow nsg : tapFlowInterface.getAll()) { + if ((queryTapFlowUUID == null || queryTapFlowUUID.equals(nsg.getID())) + && (queryTapFlowTenantID == null || queryTapFlowTenantID.equals(nsg.getTenantID())) + && (queryTapFlowName == null || queryTapFlowName.equals(nsg.getName())) + && (queryTapServiceID == null || queryTapServiceID.equals(nsg.getTapFlowServiceID())) + && (queryTapFlowDirection == null || queryTapFlowDirection.equals(nsg.getTapFlowDirection())) + && (queryTapFlowSourcePort == null + || queryTapFlowSourcePort.equals(nsg.getTapFlowSourcePort()))) { + if (fields.size() > 0) { + ans.add(nsg.extractFields(fields)); + } else { + ans.add(nsg); + } + } + } + return Response.status(HttpURLConnection.HTTP_OK).entity(new NeutronTapFlowRequest(ans)).build(); + } + + /** + * Creates new Tap Flow. + */ + @Path("{tapServiceUUID}/flows") + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_CREATED, condition = "Created"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response createTapFlow(@PathParam("tapServiceUUID") String tapServiceUUID, + final NeutronTapFlowRequest input) { + + INeutronTapFlowCRUD tapFlowInterface = getNeutronCRUD(); + + if (input.isSingleton()) { + NeutronTapFlow singleton = input.getSingleton(); + singleton.setTapFlowServiceID(tapServiceUUID); + + tapFlowInterface.addTapFlow(singleton); + } else { + throw new BadRequestException("Only Singleton tapFlow creation supported"); + } + + return Response.status(HttpURLConnection.HTTP_CREATED).entity(input).build(); + } + + /** + * Returns a specific Tap Flow. + */ + @Path("{tapServiceUUID}/flows/{tapFlowUUID}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response showTapFlow(@PathParam("tapServiceUUID") String tapServiceUUID, + @PathParam("tapFlowUUID") String tapFlowUUID, + @QueryParam("fields") List fields) { + + INeutronTapFlowCRUD tapFlowInterface = getNeutronCRUD(); + if (!tapFlowInterface.tapFlowExists(tapServiceUUID, tapFlowUUID)) { + throw new ResourceNotFoundException("Specified UUID does not Exist"); + } + + NeutronTapFlow tapFlow = tapFlowInterface.getTapFlow(tapServiceUUID, tapFlowUUID); + if (fields.size() > 0) { + return Response.status(HttpURLConnection.HTTP_OK) + .entity(new NeutronTapFlowRequest(tapFlow.extractFields(fields))).build(); + } else { + return Response.status(HttpURLConnection.HTTP_OK) + .entity(new NeutronTapFlowRequest(tapFlow)).build(); + } + } + + /** + * Updates a Tap Flow. + */ + @Path("{tapServiceUUID}/flows/{tapFlowUUID}") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response updateTapFlow(@PathParam("tapServiceUUID") String tapServiceUUID, + @PathParam("tapFlowUUID") String tapFlowUUID, + final NeutronTapFlowRequest input) { + + INeutronTapFlowCRUD tapFlowInterface = getNeutronCRUD(); + + if (!tapFlowInterface.tapFlowExists(tapServiceUUID, tapFlowUUID)) { + throw new ResourceNotFoundException("Specified UUID does not Exist"); + } + + NeutronTapFlow singleton = input.getSingleton(); + singleton.setTapFlowServiceID(tapServiceUUID); + tapFlowInterface.updateTapFlow(singleton); + + return Response.status(HttpURLConnection.HTTP_OK).entity(input).build(); + } + + /** + * Deletes a Tap Flow. + */ + @Path("{tapServiceUUID}/flows/{tapFlowUUID}") + @DELETE + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response deleteTapFlow(@PathParam("tapServiceUUID") String tapServiceUUID, + @PathParam("tapFlowUUID") String tapFlowUUID) { + + INeutronTapFlowCRUD tapFlowInterface = getNeutronCRUD(); + + if (!tapFlowInterface.tapFlowExists(tapServiceUUID, tapFlowUUID)) { + throw new ResourceNotFoundException("Specified UUID does not Exist"); + } + + tapFlowInterface.deleteTapFlow(tapServiceUUID, tapFlowUUID); + return Response.status(HttpURLConnection.HTTP_NO_CONTENT).build(); + } +} diff --git a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapFlowRequest.java b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapFlowRequest.java new file mode 100644 index 000000000..d124d821a --- /dev/null +++ b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapFlowRequest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Intel, Corp. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.northbound.api; + +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import org.opendaylight.neutron.spi.NeutronTapFlow; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public final class NeutronTapFlowRequest implements INeutronRequest { + @XmlElement(name = "tap_flow") + NeutronTapFlow singleton; + + @XmlElement(name = "tap_flows") + List bulkRequest; + + NeutronTapFlowRequest() { + } + + NeutronTapFlowRequest(List bulk) { + bulkRequest = bulk; + } + + NeutronTapFlowRequest(NeutronTapFlow tf) { + singleton = tf; + } +} diff --git a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapServiceNorthbound.java b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapServiceNorthbound.java new file mode 100644 index 000000000..0c3ee715a --- /dev/null +++ b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapServiceNorthbound.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017 Intel, Corp. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.northbound.api; + +import java.net.HttpURLConnection; +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.neutron.spi.INeutronTapServiceCRUD; +import org.opendaylight.neutron.spi.NeutronTapService; + +@Path("/tap/services") +public final class NeutronTapServiceNorthbound + extends AbstractNeutronNorthbound { + + private static final String RESOURCE_NAME = "Tap Service"; + + @Override + protected String getResourceName() { + return RESOURCE_NAME; + } + + /** + * Returns a list of all Tap Services. + */ + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response listGroups( + // return fields + @QueryParam("fields") List fields, + // OpenStack Tap Service attributes + @QueryParam("id") String queryTapServiceUUID, + @QueryParam("tenant_id") String queryTapServiceTenantID, + @QueryParam("name") String queryTapServiceName, + @QueryParam("port_id") String queryTapServicePortID, + // pagination + @QueryParam("limit") String limit, + @QueryParam("marker") String marker, + @QueryParam("page_reverse") String pageReverse) { + INeutronTapServiceCRUD tapServiceInterface = getNeutronCRUD(); + List ans = new ArrayList<>(); + for (NeutronTapService nsg : tapServiceInterface.getAll()) { + if ((queryTapServiceUUID == null || queryTapServiceUUID.equals(nsg.getID())) + && (queryTapServiceTenantID == null || queryTapServiceTenantID.equals(nsg.getTenantID())) + && (queryTapServiceName == null || queryTapServiceName.equals(nsg.getName())) + && (queryTapServicePortID == null || queryTapServicePortID.equals(nsg.getTapServicePortID()))) { + if (fields.size() > 0) { + ans.add(nsg.extractFields(fields)); + } else { + ans.add(nsg); + } + } + } + return Response.status(HttpURLConnection.HTTP_OK).entity(new NeutronTapServiceRequest(ans)).build(); + } + + /** + * Returns a specific Tap Service. + */ + @Path("{tapServiceUUID}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAUTHORIZED, condition = "Unauthorized"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_IMPLEMENTED, condition = "Not Implemented"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response showTapService(@PathParam("tapServiceUUID") String tapServiceUUID, + @QueryParam("fields") List fields) { + return show(tapServiceUUID, fields); + } + + /** + * Creates new Tap Service. + */ + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_CREATED, condition = "Created"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response createTapService(final NeutronTapServiceRequest input) { + return create(input); + } + + /** + * Updates a Tap Service. + */ + @Path("{tapServiceUUID}") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_OK, condition = "Operation successful"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response updateTapService(@PathParam("tapServiceUUID") String tapServiceUUID, + final NeutronTapServiceRequest input) { + return update(tapServiceUUID, input); + } + + /** + * Deletes a Tap Service. + */ + @Path("{tapServiceUUID}") + @DELETE + @StatusCodes({ @ResponseCode(code = HttpURLConnection.HTTP_NO_CONTENT, condition = "No Content"), + @ResponseCode(code = HttpURLConnection.HTTP_NOT_FOUND, condition = "Not Found"), + @ResponseCode(code = HttpURLConnection.HTTP_UNAVAILABLE, condition = "No providers available") }) + public Response deleteTapService(@PathParam("tapServiceUUID") String tapServiceUUID) { + return delete(tapServiceUUID); + } +} diff --git a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapServiceRequest.java b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapServiceRequest.java new file mode 100644 index 000000000..456e5dd2b --- /dev/null +++ b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/NeutronTapServiceRequest.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017 Intel, Corp. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.northbound.api; + +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import org.opendaylight.neutron.spi.NeutronTapService; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public final class NeutronTapServiceRequest implements INeutronRequest { + @XmlElement(name = "tap_service") + NeutronTapService singleton; + + @XmlElement(name = "tap_services") + List bulkRequest; + + NeutronTapServiceRequest() { + } + + NeutronTapServiceRequest(List bulk) { + bulkRequest = bulk; + } + + NeutronTapServiceRequest(NeutronTapService taas) { + singleton = taas; + } +} diff --git a/resources/Neutron_Northbound_Taas_Rest.postman_collection.json b/resources/Neutron_Northbound_Taas_Rest.postman_collection.json new file mode 100644 index 000000000..b44d6f638 --- /dev/null +++ b/resources/Neutron_Northbound_Taas_Rest.postman_collection.json @@ -0,0 +1,255 @@ +{ + "variables": [], + "info": { + "name": "Tap_As_A_Service", + "_postman_id": "abbb6f28-ad96-a06a-ce4f-b289d92419e8", + "description": "", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/", + "method": "POST", + "header": [ + { + "key": "Basic", + "value": "YWRtaW46YWRtaW4=", + "description": "" + }, + { + "key": "Accept", + "value": "application/json", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\"tap_service\": {\"id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\",\n \"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\", \n \"name\" : \"tap-service-test\",\n \"port_id\": \"311d75c3-4da8-4267-8aed-6dbb19a3dcfe\" }}\n" + }, + "description": "Create a Tap Service" + }, + "response": [] + }, + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546", + "method": "PUT", + "header": [ + { + "key": "Basic", + "value": "YWRtaW46YWRtaW4=", + "description": "" + }, + { + "key": "Accept", + "value": "application/json", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\"tap_service\": {\"id\": \"b6440bbb-35f3-48ab-8eae-69c60aef3546\",\n \"tenant_id\": \"aa902936679e4ea29bfe1158e3450a14\",\n \"name\" : \"tap-service-test\",\n \"port_id\": \"211d75c3-4da8-4267-8aed-6dbb19a3dcfe\" }}\n" + }, + "description": "Update a Tap Service" + }, + "response": [] + }, + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/", + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": {}, + "description": "View the existing Tap Service" + }, + "response": [] + }, + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546", + "method": "DELETE", + "header": [ + { + "key": "Basic", + "value": "YWRtaW46YWRtaW4=", + "description": "" + }, + { + "key": "Accept", + "value": "application/json", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "Delete the Tap Service with the ID" + }, + "response": [] + }, + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546/flows", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546/flows", + "method": "POST", + "header": [ + { + "key": "Basic", + "value": "YWRtaW46YWRtaW4=", + "description": "" + }, + { + "key": "Accept", + "value": "application/json", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\"tap_flow\": {\"id\": \"f6220bbb-35f3-48ab-8eae-69c60aef3546\",\n \"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\", \n \"name\" : \"tap-flow-test\",\n \"tap_service_id\" : \"b6440bbb-35f3-48ab-8eae-69c60aef3546\",\n \"source_port\": \"411d75c3-4da8-4267-8aed-6dbb19a3dcfe\",\n \"direction\": \"BOTH\"}}\n" + }, + "description": "" + }, + "response": [] + }, + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546/flows copy", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546", + "method": "PUT", + "header": [ + { + "key": "Basic", + "value": "YWRtaW46YWRtaW4=", + "description": "" + }, + { + "key": "Accept", + "value": "application/json", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\"tap_flow\": {\"id\": \"f6220bbb-35f3-48ab-8eae-69c60aef3546\",\n \"tenant_id\": \"aa902936679e4ea29bfe1158e3450a13\", \n \"name\" : \"tap-flow-test2\",\n \"tap_service_id\" : \"b6440bbb-35f3-48ab-8eae-69c60aef3546\",\n \"source_port\": \"611d75c3-4da8-4267-8aed-6dbb19a3dcfe\",\n \"direction\": \"IN\"}}\n" + }, + "description": "" + }, + "response": [] + }, + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546 copy", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546", + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": {}, + "description": "View the existing Tap Service" + }, + "response": [] + }, + { + "name": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/services/b6440bbb-35f3-48ab-8eae-69c60aef3546 copy", + "request": { + "url": "http://{{CONTROLLER-IP}}:{{PORT}}/controller/nb/v2/neutron/tap/flows/b6440bbb-35f3-48ab-8eae-69c60aef3546/flows/f6220bbb-35f3-48ab-8eae-69c60aef3546", + "method": "DELETE", + "header": [ + { + "key": "Basic", + "value": "YWRtaW46YWRtaW4=", + "description": "" + }, + { + "key": "Accept", + "value": "application/json", + "description": "" + }, + { + "key": "Content-Type", + "value": "application/json", + "description": "" + }, + { + "key": "Authorization", + "value": "Basic YWRtaW46YWRtaW4=", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "description": "Delete the Tap Service with the ID" + }, + "response": [] + } + ] +} diff --git a/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTapFlowInterface.java b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTapFlowInterface.java new file mode 100644 index 000000000..69682fefd --- /dev/null +++ b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTapFlowInterface.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2017 Intel Corporation and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.transcriber; + +import com.google.common.collect.ImmutableBiMap; +import com.google.common.util.concurrent.CheckedFuture; +import java.util.List; +import java.util.concurrent.ExecutionException; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.neutron.spi.INeutronTapFlowCRUD; +import org.opendaylight.neutron.spi.NeutronTapFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.DirectionBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.DirectionBoth; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.DirectionIn; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.DirectionOut; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.TapServiceAttributes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.service.attributes.TapFlows; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.service.attributes.tap.flows.TapFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.service.attributes.tap.flows.TapFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.service.attributes.tap.flows.TapFlowKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.services.attributes.TapServices; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.services.attributes.tap.services.TapService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.services.attributes.tap.services.TapServiceKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class NeutronTapFlowInterface + extends AbstractTranscriberInterface + implements INeutronTapFlowCRUD { + + private static final Logger LOG = LoggerFactory.getLogger(NeutronTapFlowInterface.class); + + private static final ImmutableBiMap, + String> DIRECTION_MAP = new ImmutableBiMap.Builder, String>() + .put(DirectionOut.class, "OUT") + .put(DirectionIn.class, "IN") + .put(DirectionBoth.class, "BOTH").build(); + + NeutronTapFlowInterface(DataBroker db) { + super(TapFlowBuilder.class, db); + } + + protected InstanceIdentifier createTapFlowInstanceIdentifier(String tapServiceUUID, TapFlow item) { + return InstanceIdentifier.create(Neutron.class) + .child(TapServices.class) + .child(TapService.class, new TapServiceKey(toUuid(tapServiceUUID))) + .child(TapFlows.class).child(TapFlow.class, item.getKey()); + } + + @Override + protected List getDataObjectList(TapFlows flows) { + return flows.getTapFlow(); + } + + @Override + protected NeutronTapFlow fromMd(TapFlow flow) { + final NeutronTapFlow answer = new NeutronTapFlow(); + fromMdBaseAttributes(flow, answer); + if (flow.getTapServiceId() != null) { + answer.setTapFlowServiceID(flow.getTapServiceId().getValue()); + } + if (flow.getSourcePort() != null) { + answer.setTapFlowSourcePort(flow.getSourcePort().getValue()); + } + if (flow.getDirection() != null) { + answer.setTapFlowDirection(DIRECTION_MAP.get(flow.getDirection())); + } + + return answer; + } + + @Override + protected TapFlow toMd(NeutronTapFlow flow) { + final TapFlowBuilder flowBuilder = new TapFlowBuilder(); + toMdBaseAttributes(flow, flowBuilder); + if (flow.getTapFlowServiceID() != null) { + flowBuilder.setTapServiceId(toUuid(flow.getTapFlowServiceID())); + } + if (flow.getTapFlowSourcePort() != null) { + flowBuilder.setSourcePort(toUuid(flow.getTapFlowSourcePort())); + } + if (flow.getTapFlowDirection() != null) { + final ImmutableBiMap> mapper = DIRECTION_MAP.inverse(); + flowBuilder.setDirection(mapper.get(flow.getTapFlowDirection())); + } + + return flowBuilder.build(); + } + + public boolean tapFlowExists(String tapServiceUUID, String tapFlowUUID) { + final TapFlow dataObject = readMd(createTapFlowInstanceIdentifier(tapServiceUUID, toMd(tapFlowUUID))); + return dataObject != null; + } + + private boolean tapServiceExists(String tapServiceUUID) { + final TapService tapService = readMd(InstanceIdentifier.create(Neutron.class).child(TapServices.class) + .child(TapService.class, new TapServiceKey(toUuid(tapServiceUUID)))); + return tapService != null; + } + + + private boolean updateTapFlowMd(NeutronTapFlow tapFlow) { + final WriteTransaction transaction = getDataBroker().newWriteOnlyTransaction(); + final TapFlow item = toMd(tapFlow); + final InstanceIdentifier iid = createTapFlowInstanceIdentifier(tapFlow.getTapFlowServiceID(), item); + transaction.put(LogicalDatastoreType.CONFIGURATION, iid, item, true); + final CheckedFuture future = transaction.submit(); + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Transaction Failed ", e); + return false; + } + return true; + } + + private boolean removeTapFlowMd(String tapServiceUUID, String tapFlowUUID) { + final WriteTransaction transaction = getDataBroker().newWriteOnlyTransaction(); + final InstanceIdentifier iid = createTapFlowInstanceIdentifier(tapServiceUUID, toMd(tapFlowUUID)); + transaction.delete(LogicalDatastoreType.CONFIGURATION, iid); + final CheckedFuture future = transaction.submit(); + try { + future.get(); + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Transation failed ", e); + return false; + } + return true; + } + + private boolean addTapFlowMd(NeutronTapFlow tapFlow) { + return updateTapFlowMd(tapFlow); + } + + @Override + public boolean updateTapFlow(NeutronTapFlow tapFlow) { + return updateTapFlowMd(tapFlow); + } + + @Override + public boolean addTapFlow(NeutronTapFlow tapFlow) { + if (!tapServiceExists(tapFlow.getTapFlowServiceID())) { + return false; + } + if (tapFlowExists(tapFlow.getTapFlowServiceID(), tapFlow.getID())) { + return false; + } + addTapFlowMd(tapFlow); + return true; + } + + @Override + public NeutronTapFlow getTapFlow(String tapServiceUUID, String tapFlowUUID) { + final TapFlow tapFlow = readMd(createTapFlowInstanceIdentifier(tapServiceUUID, toMd(tapFlowUUID))); + if (tapFlow == null) { + return null; + } + return fromMd(tapFlow); + } + + @Override + public boolean deleteTapFlow(String tapServiceUUID, String tapFlowUUID) { + return removeTapFlowMd(tapServiceUUID, tapFlowUUID); + } +} diff --git a/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTapServiceInterface.java b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTapServiceInterface.java new file mode 100644 index 000000000..8e304f61a --- /dev/null +++ b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTapServiceInterface.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017 Intel Corporation and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.neutron.transcriber; + +import java.util.List; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.neutron.spi.INeutronTapServiceCRUD; +import org.opendaylight.neutron.spi.NeutronTapService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.services.attributes.TapServices; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.services.attributes.tap.services.TapService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.services.attributes.tap.services.TapServiceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.tapaas.rev171024.tap.services.attributes.tap.services.TapServiceKey; + + + +public final class NeutronTapServiceInterface + extends AbstractNeutronInterface + implements INeutronTapServiceCRUD { + NeutronTapServiceInterface(DataBroker db) { + super(TapServiceBuilder.class, db); + } + + @Override + protected List getDataObjectList(TapServices services) { + return services.getTapService(); + } + + @Override + protected NeutronTapService fromMd(TapService service) { + final NeutronTapService answer = new NeutronTapService(); + fromMdBaseAttributes(service, answer); + if (service.getPortId() != null) { + answer.setTapServicePortID(service.getPortId().getValue()); + } + return answer; + } + + @Override + protected TapService toMd(NeutronTapService service) { + final TapServiceBuilder serviceBuilder = new TapServiceBuilder(); + toMdBaseAttributes(service, serviceBuilder); + if (service.getTapServicePortID() != null) { + serviceBuilder.setPortId(toUuid(service.getTapServicePortID())); + } + return serviceBuilder.build(); + } +} diff --git a/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTranscriberProvider.java b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTranscriberProvider.java index 28fcabafe..9e62424d4 100644 --- a/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTranscriberProvider.java +++ b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/NeutronTranscriberProvider.java @@ -41,6 +41,8 @@ import org.opendaylight.neutron.spi.INeutronSFCPortPairGroupCRUD; import org.opendaylight.neutron.spi.INeutronSecurityGroupCRUD; import org.opendaylight.neutron.spi.INeutronSecurityRuleCRUD; import org.opendaylight.neutron.spi.INeutronSubnetCRUD; +import org.opendaylight.neutron.spi.INeutronTapFlowCRUD; +import org.opendaylight.neutron.spi.INeutronTapServiceCRUD; import org.opendaylight.neutron.spi.INeutronTrunkCRUD; import org.opendaylight.neutron.spi.INeutronVpnIkePolicyCRUD; import org.opendaylight.neutron.spi.INeutronVpnIpSecPolicyCRUD; @@ -104,6 +106,8 @@ public final class NeutronTranscriberProvider implements NeutronTranscriber { registerCRUDInterface(INeutronSecurityGroupCRUD.class, new NeutronSecurityGroupInterface(db)); registerCRUDInterface(INeutronSecurityRuleCRUD.class, new NeutronSecurityRuleInterface(db)); registerCRUDInterface(INeutronSubnetCRUD.class, new NeutronSubnetInterface(db)); + registerCRUDInterface(INeutronTapServiceCRUD.class, new NeutronTapServiceInterface(db)); + registerCRUDInterface(INeutronTapFlowCRUD.class, new NeutronTapFlowInterface(db)); registerCRUDInterface(INeutronTrunkCRUD.class, new NeutronTrunkInterface(db)); registerCRUDInterface(INeutronVpnIkePolicyCRUD.class, new NeutronVpnIkePolicyInterface(db)); registerCRUDInterface(INeutronVpnIpSecPolicyCRUD.class, new NeutronVpnIpSecPolicyInterface(db));