* 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 NeutronSecurityRuleTests {
+ private static final String TEST_SECURITY_GROUP_ID = "b60490fe-60a5-40be-af63-1d641381b784";
+
private final String base;
public NeutronSecurityRuleTests(String base) {
HttpUtils.test_fetch(url, "Security Rule Collection GET failed");
}
- private String singleton_sr_create_test() {
+ private void singleton_sr_without_groupid_create_test(int responseCode) {
+ String url = base + "/security-group-rules";
+ String content = " {\"security_group_rule\": " + "{\"remote_group_id\": null, \"direction\": \"ingress\", "
+ + "\"remote_ip_prefix\": null, \"protocol\": \"tcp\", " + "\"ethertype\": \"IPv6\", \"tenant_id\": "
+ + "\"00f340c7c3b34ab7be1fc690c05a0275\", \"port_range_max\": 77, " + "\"port_range_min\": 77, "
+ + "\"id\": \"9b4be7fa-e56e-40fb-9516-1f0fa9185669\"}}"; // no security_group_id
+ HttpUtils.test_create(url, responseCode, content, "Security Rule Singleton Post Failed");
+ }
+
+ private String singleton_sr_create_test(int responseCode) {
String url = base + "/security-group-rules";
String content = " {\"security_group_rule\": " + "{\"remote_group_id\": null, \"direction\": \"ingress\", "
+ "\"remote_ip_prefix\": null, \"protocol\": \"tcp\", " + "\"ethertype\": \"IPv6\", \"tenant_id\": "
+ "\"00f340c7c3b34ab7be1fc690c05a0275\", \"port_range_max\": 77, " + "\"port_range_min\": 77, "
+ "\"id\": \"9b4be7fa-e56e-40fb-9516-1f0fa9185669\", " + "\"security_group_id\": "
- + "\"b60490fe-60a5-40be-af63-1d641381b784\"}}";
- HttpUtils.test_create(url, content, "Security Rule Singleton Post Failed");
+ + "\"" + TEST_SECURITY_GROUP_ID + "\"}}";
+ HttpUtils.test_create(url, responseCode, content, "Security Rule Singleton Post Failed");
return content;
}
String url = base + "/security-group-rules";
String content = " {\"security_group_rules\": [" + "{" + " \"id\": \"35fb0f34-c8d3-416d-a205-a2c75f7b8e22\","
+ " \"direction\": \"egress\"," + " \"ethertype\": \"IPv6\"," + " \"protocol\": \"tcp\","
- + " \"security_group_id\": \"70f1b157-e79b-44dc-85a8-7de0fc9f2aab\","
+ + " \"security_group_id\": \"b60490fe-60a5-40be-af63-1d641381b784\","
+ " \"tenant_id\": \"2640ee2ac2474bf3906e482047204fcb\"" + "}," + "{"
+ " \"id\": \"63814eed-bc12-4fe4-8b17-2af178224c71\"," + " \"direction\": \"egress\","
+ " \"ethertype\": \"IPv4\"," + " \"protocol\": \"6\","
- + " \"security_group_id\": \"70f1b157-e79b-44dc-85a8-7de0fc9f2aab\","
+ + " \"security_group_id\": \"b60490fe-60a5-40be-af63-1d641381b784\","
+ " \"tenant_id\": \"2640ee2ac2474bf3906e482047204fcb\"" + "}," + "{"
+ " \"id\": \"ccb9823e-559b-4d84-b656-2739f8e56d89\"," + " \"direction\": \"ingress\","
+ " \"ethertype\": \"IPv6\"," + " \"protocol\": 6,"
- + " \"remote_group_id\": \"70f1b157-e79b-44dc-85a8-7de0fc9f2aab\","
- + " \"security_group_id\": \"70f1b157-e79b-44dc-85a8-7de0fc9f2aab\","
+ + " \"remote_group_id\": \"b60490fe-60a5-40be-af63-1d641381b784\","
+ + " \"security_group_id\": \"b60490fe-60a5-40be-af63-1d641381b784\","
+ " \"tenant_id\": \"2640ee2ac2474bf3906e482047204fcb\"" + "}," + "{"
+ " \"id\": \"fbc3f809-7378-40a4-822f-7a70f6ccba98\"," + " \"direction\": \"ingress\","
+ " \"ethertype\": \"IPv4\"," + " \"protocol\": \"udp\","
- + " \"remote_group_id\": \"70f1b157-e79b-44dc-85a8-7de0fc9f2aab\","
- + " \"security_group_id\": \"70f1b157-e79b-44dc-85a8-7de0fc9f2aab\","
+ + " \"remote_group_id\": \"b60490fe-60a5-40be-af63-1d641381b784\","
+ + " \"security_group_id\": \"b60490fe-60a5-40be-af63-1d641381b784\","
+ " \"tenant_id\": \"2640ee2ac2474bf3906e482047204fcb\"" + "}" + "]}";
HttpUtils.test_create(url, content, "Security Rule Multiple Post Failed");
}
+ "\"remote_ip_prefix\": null, \"protocol\": \"tcp\", " + "\"ethertype\": \"IPv6\", \"tenant_id\": "
+ "\"00f340c7c3b34ab7be1fc690c05a0275\", \"port_range_max\": 77, " + "\"port_range_min\": 77, "
+ "\"id\": \"9b4be7fa-e56e-40fb-9516-1f0fa9185669\", " + "\"security_group_id\": "
- + "\"b60490fe-60a5-40be-af63-1d641381b784\"}}";
+ + "\"" + TEST_SECURITY_GROUP_ID + "\"}}";
HttpUtils.test_modify(url, content, "Security Rule Singleton Put Failed");
}
+ "\"ethertype\": \"IPv4\", \"tenant_id\": "
+ "\"00f340c7c3b34ab7be1fc690c05a0275\", \"port_range_max\": 77, " + "\"port_range_min\": 77, "
+ "\"id\": \"01234567-0123-0123-0123-01234567890a\", " + "\"security_group_id\": "
- + "\"b60490fe-60a5-40be-af63-1d641381b784\"}}";
+ + "\"" + TEST_SECURITY_GROUP_ID + "\"}}";
HttpUtils.test_create(url, content, "Security Rule bug4043 IPv4 Failed");
url = url + "/01234567-0123-0123-0123-01234567890a";
public static void runTests(String base) {
NeutronSecurityRuleTests securityRuleTester = new NeutronSecurityRuleTests(base);
- String createJsonString = securityRuleTester.singleton_sr_create_test();
+ securityRuleTester.singleton_sr_without_groupid_create_test(500);
+ securityRuleTester.singleton_sr_create_test(HttpUtils.HTTP_MISSING_DEPENDENCY);
+ new NeutronSecurityGroupTests(base).singleton_sg_create(TEST_SECURITY_GROUP_ID);
+ String createJsonString = securityRuleTester.singleton_sr_create_test(201);
securityRuleTester.singleton_sr_get_with_one_query_item_test(createJsonString);
securityRuleTester.multiple_sr_create_test();
securityRuleTester.singleton_sr_modify_test();
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
+import java.util.function.Function;
import javax.annotation.PreDestroy;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
import org.opendaylight.neutron.spi.INeutronBaseAttributes;
import org.opendaylight.neutron.spi.INeutronCRUD;
import org.opendaylight.neutron.spi.INeutronObject;
+import org.opendaylight.neutron.spi.NeutronObject;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.attrs.rev150712.AdminAttributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.attrs.rev150712.BaseAttributes;
}
protected static Uuid toUuid(String uuid) {
- Preconditions.checkNotNull(uuid);
+ Preconditions.checkNotNull(uuid, "uuid");
Uuid result;
try {
result = new Uuid(uuid);
while (retries-- >= 0) {
final ReadWriteTransaction tx = getDataBroker().newReadWriteTransaction();
try {
- return add(input, tx);
+ if (areAllDependenciesAvailable(tx, input)) {
+ return add(input, tx);
+ } else {
+ return Result.DependencyMissing;
+ }
} catch (InterruptedException | ExecutionException e) {
// TODO replace all this with org.opendaylight.genius.infra.RetryingManagedNewTransactionRunner
if (e.getCause() instanceof OptimisticLockFailedException) {
}
return false;
}
+
+ /**
+ * Check if this particular (subclass) transcriber's dependencies are met.
+ * Default implementation just returns true. Some but not all transcribers will customize this.
+ *
+ * <p>Implementations *MUST* use the passed in transaction. They will typically call the
+ * {@link #exists(String, ReadTransaction)} method on ANOTHER transcriber with it.
+ *
+ * <p>Implementations should chain {@link #ifNonNull(Object, Function)}, or perform null safe comparisons otherwise,
+ * for any optional non-mandatory {@link NeutronObject} properties which may well be null.
+ *
+ * @param tx the transaction within which to perform reads to check for dependencies
+ * @param neutronObject the incoming main neutron object in which there may be references to dependencies
+ *
+ * @return true if all dependencies are available and
+ * {@link #add(INeutronObject)} operation can proceed; false if there
+ * are unmet dependencies, which will cause the add to abort, and a respective
+ * error code returned to the caller.
+ */
+ protected boolean areAllDependenciesAvailable(ReadTransaction tx, S neutronObject) {
+ return true;
+ }
+
+ /**
+ * Utility to perform well readable code of null-safe chains of e.g.
+ * {@link #exists(String, ReadTransaction)} method calls.
+ */
+ protected static final <X> boolean ifNonNull(
+ @Nullable X property, Function<@NonNull X, @NonNull Boolean> function) {
+ if (property != null) {
+ Boolean result = function.apply(property);
+ Preconditions.checkNotNull(result, "result");
+ return result;
+ } else {
+ // We return true, in line with the default implementation
+ // in org.opendaylight.neutron.transcriber.AbstractTranscriberInterface.
+ // areAllDependenciesAvailable(ReadTransaction, S)
+ return true;
+ }
+ }
+
}
import javax.inject.Inject;
import javax.inject.Singleton;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
import org.opendaylight.neutron.northbound.api.BadRequestException;
import org.opendaylight.neutron.spi.INeutronSecurityRuleCRUD;
import org.opendaylight.neutron.spi.NeutronSecurityRule;
String> ETHERTYPE_MAP = new ImmutableBiMap.Builder<Class<? extends EthertypeBase>, String>()
.put(EthertypeV4.class, "IPv4").put(EthertypeV6.class, "IPv6").build();
+ private final NeutronSecurityGroupInterface securityGroupInterface;
+
@Inject
- public NeutronSecurityRuleInterface(DataBroker db) {
+ public NeutronSecurityRuleInterface(DataBroker db, NeutronSecurityGroupInterface securityGroupInterface) {
super(SecurityRuleBuilder.class, db);
+ this.securityGroupInterface = securityGroupInterface;
}
@Override
}
return securityRuleBuilder.build();
}
+
+ @Override
+ protected boolean areAllDependenciesAvailable(ReadTransaction tx, NeutronSecurityRule securityRule) {
+ return securityGroupInterface.exists(securityRule.getSecurityRuleGroupID(), tx)
+ && ifNonNull(securityRule.getSecurityRemoteGroupID(),
+ remoteGroupID -> securityGroupInterface.exists(remoteGroupID, tx));
+ }
}