From db824362834c8442b0864fd42b8d45c5e4436989 Mon Sep 17 00:00:00 2001 From: Ritu Sood Date: Mon, 6 Feb 2017 18:09:04 -0800 Subject: [PATCH] Neutron Model update This patch includes Neutron API/model changes being introduced. 1) Status field to be moved to operational datastore Breaking out the status field from this patch for ease of review and merge process. Link to status field patch https://git.opendaylight.org/gerrit/#/c/51981/ 2) Project id field is going to depreciate tenant id https://lists.opendaylight.org/pipermail/neutron-dev/2016-December/001083.html This fix addresses top level tenant-id used my most models. Some models internally also use tenant-id in sub-fields. Those cases will be addressed in Nitrogen. 3) revision number field to be added. This is a monotonic counter that will be updated whenever an object is updated on the neutron server. Change-Id: I8a76fe5ff1147a9e4456c0713913377f266cec24 Signed-off-by: Ritu Sood Signed-off-by: Isaku Yamahata --- .../neutron/e2etest/ITNeutronE2E.java | 3 +- .../e2etest/NeutronProjectIdTests.java | 87 +++++++++++++++ .../e2etest/NeutronRevisionNumberTests.java | 101 ++++++++++++++++++ model/src/main/yang/neutron-attrs.yang | 15 +++ .../neutron/spi/INeutronObject.java | 8 ++ .../neutron/spi/NeutronObject.java | 38 +++++++ .../api/AbstractNeutronNorthbound.java | 19 +++- .../transcriber/AbstractNeutronInterface.java | 19 ++++ 8 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronProjectIdTests.java create mode 100644 integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronRevisionNumberTests.java diff --git a/integration/test/src/test/java/org/opendaylight/neutron/e2etest/ITNeutronE2E.java b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/ITNeutronE2E.java index 35870ac79..910ea8218 100644 --- a/integration/test/src/test/java/org/opendaylight/neutron/e2etest/ITNeutronE2E.java +++ b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/ITNeutronE2E.java @@ -116,7 +116,8 @@ public class ITNeutronE2E { NeutronSFCPortChainTests.runTests(base); NeutronSFCFlowClassifierTests.runTests(base); NeutronTrunkTests.runTests(base); - + NeutronRevisionNumberTests.runTests(base); + NeutronProjectIdTests.runTests(base); // tests related to bugs NeutronBug3812Tests.runTests(base); TempestPortsIpV6TestJSON.runTests(base); diff --git a/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronProjectIdTests.java b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronProjectIdTests.java new file mode 100644 index 000000000..1aac64975 --- /dev/null +++ b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronProjectIdTests.java @@ -0,0 +1,87 @@ +/* + * 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 NeutronProjectIdTests { + String base; + + public NeutronProjectIdTests(String base) { + this.base = base; + } + + public void collection_get_test() { + String url = base + "/fw/firewalls"; + ITNeutronE2E.test_fetch(url, "RevisionID Collection GET failed"); + } + + public String singleton_create_test() { + String url = base + "/fw/firewalls"; + String content = " { \"firewall\": { \"admin_state_up\": true," + "\"description\": \"\"," + + "\"firewall_policy_id\": \"c69933c1-b472-44f9-8226-30dc4ffd454c\"," + + "\"id\": \"4b0ef8f4-82c7-44d4-a4fb-6177f9a21977\"," + + "\"name\": \"\"," + + "\"project_id\": \"45977fa2dbd7482098dd68d0d8970117\" } }"; + ITNeutronE2E.test_create(url, content, "RevisionID Singleton Post Failed"); + return content; + } + + public void singleton_get_with_one_query_item_test(String createJsonString) { + String url = base + "/fw/firewalls"; + ITNeutronE2E.test_fetch_with_one_query_item(url, createJsonString, "firewalls"); + } + + public void modify_test() { + String url = base + "/fw/firewalls/4b0ef8f4-82c7-44d4-a4fb-6177f9a21977"; + String content = " { \"firewall\": { \"admin_state_up\": false," + "\"description\": \"\"," + + "\"firewall_policy_id\": \"c69933c1-b472-44f9-8226-30dc4ffd454c\"," + + "\"id\": \"4b0ef8f4-82c7-44d4-a4fb-6177f9a21977\"," + + "\"name\": \"\"," + + "\"project_id\": \"45977fa2dbd7482098dd68d0d8970117\" } }"; + ITNeutronE2E.test_modify(url, content, "RevisionID Singleton Post Failed"); + } + + public void element_get_test() { + String url = base + "/fw/firewalls/4b0ef8f4-82c7-44d4-a4fb-6177f9a21977"; + ITNeutronE2E.test_fetch(url, true, "RevisionID Element Get Failed"); + } + + public void delete_test() { + String url = base + "/fw/firewalls/4b0ef8f4-82c7-44d4-a4fb-6177f9a21977"; + ITNeutronE2E.test_delete(url, "RevisionID Delete Failed"); + } + + public String singleton_create_test_with_tenant_id() { + String url = base + "/fw/firewalls"; + String content = " { \"firewall\": { \"admin_state_up\": true," + "\"description\": \"\"," + + "\"firewall_policy_id\": \"c69933c1-b472-44f9-8226-30dc4ffd454c\"," + + "\"id\": \"5b0ef8f4-82c7-44d4-a4fb-6177f9a21977\"," + + "\"name\": \"\"," + + "\"tenant_id\": \"55988fb3dbd7482098dd68d0d8970228\"," + + "\"project_id\": \"45977fa2dbd7482098dd68d0d8970117\" } }"; + ITNeutronE2E.test_create(url, content, "RevisionID Singleton Post Failed"); + return content; + } + + public void delete_test_with_tenant_id() { + String url = base + "/fw/firewalls/5b0ef8f4-82c7-44d4-a4fb-6177f9a21977"; + ITNeutronE2E.test_delete(url, "RevisionID Delete Failed"); + } + + public static void runTests(String base) { + NeutronProjectIdTests tester = new NeutronProjectIdTests(base); + String createJsonString = tester.singleton_create_test(); + tester.singleton_get_with_one_query_item_test(createJsonString); + tester.element_get_test(); + tester.collection_get_test(); + tester.modify_test(); + tester.delete_test(); + tester.singleton_create_test_with_tenant_id(); + tester.delete_test_with_tenant_id(); + } +} diff --git a/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronRevisionNumberTests.java b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronRevisionNumberTests.java new file mode 100644 index 000000000..e4b40fc35 --- /dev/null +++ b/integration/test/src/test/java/org/opendaylight/neutron/e2etest/NeutronRevisionNumberTests.java @@ -0,0 +1,101 @@ +/* + * 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 NeutronRevisionNumberTests { + + String base; + + public NeutronRevisionNumberTests(String base) { + this.base = base; + } + + public void subnet_create_test() { + String url = base + "/subnets"; + String content = " { \"subnets\": [ " + " { \"allocation_pools\": [ " + + " { \"end\": \"192.168.199.254\", \"start\": \"192.168.199.2\" } ], " + + " \"cidr\": \"192.168.199.0/24\", " + " \"dns_nameservers\": [\"8.8.8.8\"], " + + " \"enable_dhcp\": true, " + " \"gateway_ip\": \"192.168.199.1\", " + + " \"host_routes\":[ { \"destination\":\"0.0.0.0/0\", " + " \"nexthop\":\"192.168.199.3\" }, " + + " { \"destination\":\"192.168.0.0/24\", " + " \"nexthop\":\"192.168.199.4\" } ], " + + " \"id\": \"1468a7a7-290d-4127-aedd-6c9449775a24\", " + " \"ip_version\": 4, " + " \"name\": \"\", " + + " \"network_id\": \"af374017-c9ae-4a1d-b799-ab73111476e2\", " + + " \"tenant_id\": \"4fd44f30292945e481c7b8a0c8908869\" }, { " + + " \"allocation_pools\": [ { \"end\": \"10.56.7.254\", \"start\": \"10.56.4.2\" } ], " + + " \"cidr\": \"10.56.4.0/22\", " + " \"dns_nameservers\": [\"8.8.8.8\", \"8.8.8.4\"], " + + " \"enable_dhcp\": true, " + " \"gateway_ip\": \"10.56.4.1\", " + + " \"host_routes\":[ { \"destination\":\"0.0.0.0/0\", " + " \"nexthop\":\"10.56.4.3\" }, " + + " { \"destination\":\"192.168.0.0/24\", " + " \"nexthop\":\"10.56.4.4\" } ], " + + " \"id\": \"c0e7435c-1512-45fb-aa9e-9a7c5932fb30\", " + " \"ip_version\": 4, " + " \"name\": \"\", " + + " \"network_id\": \"af374017-c9ae-4a1d-b799-ab73111476e2\", " + + " \"tenant_id\": \"4fd44f30292945e481c7b8a0c8908869\" } ] }"; + ITNeutronE2E.test_create(url, content, "Revision Number Post Failed"); + } + + public void subnet_update_test() { + String url = base + "/subnets/c0e7435c-1512-45fb-aa9e-9a7c5932fb30"; + String content = " { \"subnet\": { " + " \"name\": \"my_subnet\", " + " \"enable_dhcp\": true, " + + " \"network_id\": \"af374017-c9ae-4a1d-b799-ab73111476e2\", " + + " \"tenant_id\": \"4fd44f30292945e481c7b8a0c8908869\", " + + " \"dns_nameservers\": [\"8.8.8.8\", \"8.8.8.4\"], " + + " \"allocation_pools\": [ { \"start\": \"10.0.0.2\", \"end\": \"10.0.0.254\" } ], " + + " \"host_routes\": [{ \"destination\":\"192.168.0.0/24\", " + " \"nexthop\":\"10.0.0.11\" } ], " + + " \"ip_version\": 4, " + " \"gateway_ip\": \"10.0.0.1\", " + " \"cidr\": \"10.0.0.0/24\", " + + "\"revision_number\": 3, " + + " \"id\": \"c0e7435c-1512-45fb-aa9e-9a7c5932fb30\" } }"; + ITNeutronE2E.test_modify(url, content, "Revision Number Put Failed"); + } + + public void subnet_update_test_with_old_value() { + String url = base + "/subnets/c0e7435c-1512-45fb-aa9e-9a7c5932fb30"; + String content = " { \"subnet\": { " + " \"name\": \"my_subnet\", " + " \"enable_dhcp\": true, " + + " \"network_id\": \"af374017-c9ae-4a1d-b799-ab73111476e2\", " + + " \"tenant_id\": \"4fd44f30292945e481c7b8a0c8908869\", " + + " \"dns_nameservers\": [\"8.8.8.8\", \"8.8.8.4\"], " + + " \"allocation_pools\": [ { \"start\": \"10.0.0.2\", \"end\": \"10.0.0.254\" } ], " + + " \"host_routes\": [{ \"destination\":\"192.168.0.0/24\", " + " \"nexthop\":\"10.0.0.11\" } ], " + + " \"ip_version\": 4, " + " \"gateway_ip\": \"10.0.0.1\", " + " \"cidr\": \"10.0.0.0/24\", " + + "\"revision_number\": 2, " + + " \"id\": \"c0e7435c-1512-45fb-aa9e-9a7c5932fb30\" } }"; + ITNeutronE2E.test_modify(url, content, "Revision Number Put Failed"); + } + + public void subnet_update_test_with_no_value() { + String url = base + "/subnets/c0e7435c-1512-45fb-aa9e-9a7c5932fb30"; + String content = " { \"subnet\": { " + " \"name\": \"my_subnet\", " + " \"enable_dhcp\": true, " + + " \"network_id\": \"af374017-c9ae-4a1d-b799-ab73111476e2\", " + + " \"tenant_id\": \"4fd44f30292945e481c7b8a0c8908869\", " + + " \"dns_nameservers\": [\"8.8.8.8\", \"8.8.8.4\"], " + + " \"allocation_pools\": [ { \"start\": \"10.0.0.2\", \"end\": \"10.0.0.254\" } ], " + + " \"host_routes\": [{ \"destination\":\"192.168.0.0/24\", " + " \"nexthop\":\"10.0.0.11\" } ], " + + " \"ip_version\": 4, " + " \"gateway_ip\": \"10.0.0.1\", " + " \"cidr\": \"10.0.0.0/24\", " + + " \"id\": \"c0e7435c-1512-45fb-aa9e-9a7c5932fb30\" } }"; + ITNeutronE2E.test_modify(url, content, "Revision Number Put Failed"); + } + + public void subnet_element_get_test() { + String url = base + "/subnets/c0e7435c-1512-45fb-aa9e-9a7c5932fb30"; + ITNeutronE2E.test_fetch(url, true, "Revision Number Element Get Failed"); + } + + public void subnet_delete_test() { + String url = base + "/subnets/c0e7435c-1512-45fb-aa9e-9a7c5932fb30"; + ITNeutronE2E.test_delete(url, "Revision Number Element Delete Failed"); + } + + public static void runTests(String base) { + NeutronRevisionNumberTests tester = new NeutronRevisionNumberTests(base); + tester.subnet_create_test(); + tester.subnet_element_get_test(); + tester.subnet_update_test(); + tester.subnet_update_test_with_old_value(); + tester.subnet_update_test_with_no_value(); + tester.subnet_delete_test(); + } +} diff --git a/model/src/main/yang/neutron-attrs.yang b/model/src/main/yang/neutron-attrs.yang index 1d1f41c83..a2d2bf669 100644 --- a/model/src/main/yang/neutron-attrs.yang +++ b/model/src/main/yang/neutron-attrs.yang @@ -40,9 +40,24 @@ module neutron-attrs { } leaf tenant-id { + status deprecated; type yang:uuid; description "The UUID of the tenant that will own the object."; } + + leaf project-id { + type string { + length "0..255"; + } + description "The id of the project."; + } + + leaf revision-number { + type int64; + description "The revision number of the resource. Used as monotonic + counter that is updated whenever an object is updated + on neutron server"; + } } grouping admin-attributes { diff --git a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronObject.java b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronObject.java index ad2913c73..9d9bbcf57 100644 --- a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronObject.java +++ b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/INeutronObject.java @@ -27,6 +27,14 @@ public interface INeutronObject { void setTenantID(Uuid tenantID); + String getProjectID(); + + void setProjectID(String projectID); + + Long getRevisionNumber(); + + void setRevisionNumber(Long revisionNumber); + void initDefaults(); T extractFields(List fields); diff --git a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronObject.java b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronObject.java index f6858669e..61e9b030b 100644 --- a/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronObject.java +++ b/neutron-spi/src/main/java/org/opendaylight/neutron/spi/NeutronObject.java @@ -27,6 +27,12 @@ public abstract class NeutronObject extends NeutronID @XmlElement(name = "tenant_id") String tenantID; + @XmlElement(name = "project_id") + String projectID; + + @XmlElement(name = "revision_number") + Long revisionNumber; + public NeutronObject() { super(); } @@ -57,8 +63,34 @@ public abstract class NeutronObject extends NeutronID return "NeutronObject [id=" + uuid + ", tenantID=" + tenantID + "]"; } + @Override + public void setProjectID(String projectID) { + this.projectID = projectID; + } + + @Override + public String getProjectID() { + return this.projectID; + } + + @Override + public Long getRevisionNumber() { + return revisionNumber; + } + + @Override + public void setRevisionNumber(Long revisionNumber) { + this.revisionNumber = revisionNumber; + } + @Override public void initDefaults() { + if (projectID != null && tenantID == null) { + tenantID = projectID; + } + if (projectID == null && tenantID != null) { + projectID = tenantID; + } } @Override @@ -71,5 +103,11 @@ public abstract class NeutronObject extends NeutronID if (field.equals("tenant_id")) { ans.setTenantID(this.getTenantID()); } + if (field.equals("project_id")) { + ans.setProjectID(this.getProjectID()); + } + if (field.equals("revision_number")) { + ans.setRevisionNumber(this.getRevisionNumber()); + } } } diff --git a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/AbstractNeutronNorthbound.java b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/AbstractNeutronNorthbound.java index cad9f32bf..76c796701 100644 --- a/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/AbstractNeutronNorthbound.java +++ b/northbound-api/src/main/java/org/opendaylight/neutron/northbound/api/AbstractNeutronNorthbound.java @@ -121,6 +121,21 @@ public abstract class AbstractNeutronNorthbound, R e protected void updateDelta(String uuid, T delta, T original) { } + private boolean checkRevisionNumber(T original, T delta) { + // If new update is null ignore the original revision number + if (delta.getRevisionNumber() == null) { + return false; + } + // If what is stored is null no need for comparison + if (original.getRevisionNumber() == null) { + return false; + } + if (original.getRevisionNumber() > delta.getRevisionNumber()) { + return true; + } + return false; + } + protected Response update(String uuid, final R input) { I neutronCRUD = getNeutronCRUD(); if (!input.isSingleton()) { @@ -131,8 +146,10 @@ public abstract class AbstractNeutronNorthbound, R e if (original == null) { throw new ResourceNotFoundException(uuidNoExist()); } + if (checkRevisionNumber(original, delta)) { + return Response.status(HttpURLConnection.HTTP_OK).build(); + } updateDelta(uuid, delta, original); - /* * update the object and return it */ diff --git a/transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractNeutronInterface.java b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractNeutronInterface.java index 0244a16e5..58e7456d9 100644 --- a/transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractNeutronInterface.java +++ b/transcriber/src/main/java/org/opendaylight/neutron/transcriber/AbstractNeutronInterface.java @@ -78,9 +78,11 @@ public abstract class AbstractNeutronInterface> builderClass; private final Method setUuid; private final Method setTenantId; + private final Method setProjectId; private final Method setName; private final Method setAdminStateUp; private final Method setStatus; + private final Method setRevisionNumber; AbstractNeutronInterface(Class> builderClass, DataBroker db) { this.db = Preconditions.checkNotNull(db); @@ -101,9 +103,14 @@ public abstract class AbstractNeutronInterface, M extends BaseAttributes, B extends Builder> @@ -162,6 +175,9 @@ public abstract class AbstractNeutronInterface, M extends BaseAttributes & AdminAttributes, B extends Builder> -- 2.36.6