Fix connection when slave role request is unsupported 18/58518/6
authormiroslav.macko <miroslav.macko@pantheon.tech>
Thu, 8 Jun 2017 13:29:56 +0000 (15:29 +0200)
committerMiroslav Macko <miroslav.macko@pantheon.tech>
Thu, 15 Jun 2017 12:18:35 +0000 (12:18 +0000)
- Allow the switch connection when OFPRRFC_UNSUP is received
- Set feature exception for getGenerationIdFromDevice RPC error
- Add unit test

Resolves: bug 7664

Change-Id: If8d7d045fb516f55346333cc7e60d0ccb2135efd
Signed-off-by: miroslav.macko <miroslav.macko@pantheon.tech>
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/RoleService.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/sal/SalRoleServiceImpl.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/sal/SalRoleServiceImplTest.java

index 446f8372a8da98e4e78bc9525b8de6430ec12870..8abfd8b954acdab2739ce5c5b56df81173a831ac 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.impl.role.RoleChangeException;
 import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ControllerRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
@@ -80,9 +81,8 @@ public class RoleService extends AbstractSimpleService<RoleRequestInputBuilder,
                 } else {
                     LOG.error("getGenerationIdFromDevice RPC error " +
                             roleRequestOutputRpcResult.getErrors().iterator().next().getInfo());
-
+                    finalFuture.setException(new RoleChangeException(ErrorUtil.errorsToString(roleRequestOutputRpcResult.getErrors())));
                 }
-
             }
 
             @Override
index ee3beed681bba0210c8be1ebdfd4cf8185496f15..e6a26f88b6117f77ae1e465f782a5ccba547043f 100644 (file)
@@ -16,8 +16,6 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
 import java.math.BigInteger;
 import java.util.concurrent.Future;
-import java.util.concurrent.Semaphore;
-import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext.CONNECTION_STATE;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
@@ -26,12 +24,14 @@ import org.opendaylight.openflowplugin.impl.role.RoleChangeException;
 import org.opendaylight.openflowplugin.impl.services.AbstractSimpleService;
 import org.opendaylight.openflowplugin.impl.services.RoleService;
 import org.opendaylight.openflowplugin.impl.services.util.ServiceException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
@@ -46,6 +46,8 @@ public final class SalRoleServiceImpl extends AbstractSimpleService<SetRoleInput
 
     private static final int MAX_RETRIES = 42;
 
+    private static final String ROLE_REQUEST_UNSUPPORTED = ErrorType.ROLEREQUESTFAILED.name().concat(" code UNSUP");
+
     private final DeviceContext deviceContext;
     private final RoleService roleService;
 
@@ -124,15 +126,31 @@ public final class SalRoleServiceImpl extends AbstractSimpleService<SetRoleInput
                     LOG.debug("setRoleOutput received after roleChangeTask execution:{}", result);
                     future.set(RpcResultBuilder.<SetRoleOutput> success().withResult(result.getResult()).build());
                 } else {
-                    LOG.error("setRole() failed with errors, will retry: {} times.", MAX_RETRIES - retryCounter);
-                    repeaterForChangeRole(future, input, (retryCounter + 1));
+                    final boolean present = result
+                            .getErrors()
+                            .stream()
+                            .anyMatch(rpcError -> (rpcError.getMessage().contains(ROLE_REQUEST_UNSUPPORTED)));
+
+                    if (!present) {
+                        LOG.warn("setRole() failed with errors, will retry: {} times.", MAX_RETRIES - retryCounter);
+                        repeaterForChangeRole(future, input, (retryCounter + 1));
+                    } else {
+                        LOG.warn("setRole() failed with error - role request unsupported.");
+                        future.set(result);
+                    }
                 }
             }
 
             @Override
             public void onFailure(final Throwable t) {
-                LOG.error("Exception in setRole(), will retry: {} times.", t, MAX_RETRIES - retryCounter);
-                repeaterForChangeRole(future, input, (retryCounter + 1));
+                if (!t.getMessage().contains(ROLE_REQUEST_UNSUPPORTED)) {
+                    LOG.warn("Exception in setRole(), will retry: {} times.", t, MAX_RETRIES - retryCounter);
+                    repeaterForChangeRole(future, input, (retryCounter + 1));
+                } else {
+                    LOG.warn("Exception in setRole() - role request unsupported.", t);
+                    future.set(RpcResultBuilder.<SetRoleOutput>failed()
+                            .withError(RpcError.ErrorType.APPLICATION, t.getMessage()).build());
+                }
             }
         });
     }
index 74ec78da7640b71506f683eecfeced328db5f587..20f26350002ead576f5c7125fec4fb7d99f9a0e4 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.openflowplugin.impl.services.sal;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -30,7 +31,6 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.openflowplugin.impl.services.sal.SalRoleServiceImpl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
@@ -47,6 +47,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetR
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 
@@ -94,6 +95,11 @@ public class SalRoleServiceImplTest {
 
     private static long testXid = 100L;
 
+    private static final String ROLEREQUESTFAILED =
+            org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ErrorType.ROLEREQUESTFAILED.name();
+
+    private static final String ROLES_UNSUPPORTED = "Device reported error type "+ ROLEREQUESTFAILED +" code UNSUP";
+
     private NodeRef nodeRef;
 
     @Before
@@ -151,6 +157,31 @@ public class SalRoleServiceImplTest {
 
     }
 
+    @Test
+    public void testSetRoleUnsupported() throws Exception {
+        ListenableFuture<RpcResult<RoleRequestOutput>> futureOutput =
+                RpcResultBuilder.<RoleRequestOutput>failed()
+                        .withError(ErrorType.APPLICATION, ROLES_UNSUPPORTED)
+                        .buildFuture();
+
+        Mockito.when(mockRequestContext.getFuture()).thenReturn(futureOutput);
+
+        SalRoleService salRoleService = new SalRoleServiceImpl(mockRequestContextStack, mockDeviceContext);
+
+        SetRoleInput setRoleInput = new SetRoleInputBuilder()
+                .setControllerRole(OfpRole.BECOMESLAVE)
+                .setNode(nodeRef)
+                .build();
+
+        Future<RpcResult<SetRoleOutput>> future = salRoleService.setRole(setRoleInput);
+
+        RpcResult<SetRoleOutput> roleOutputRpcResult = future.get(5, TimeUnit.SECONDS);
+        assertNotNull("RpcResult from future cannot be null.", roleOutputRpcResult);
+        assertFalse("RpcResult from future is successful.", roleOutputRpcResult.isSuccessful());
+        assertEquals(ROLES_UNSUPPORTED, roleOutputRpcResult
+                .getErrors().iterator().next().getMessage());
+    }
+
     @Test
     public void testDuplicateRoles() throws Exception {
         // set role to slave