BUG-6858: adapt to ise api, wire harvestAll to template-provider 13/46613/1
authorMichal Rehak <mirehak@cisco.com>
Mon, 3 Oct 2016 13:15:13 +0000 (15:15 +0200)
committerMichal Rehak <mirehak@cisco.com>
Thu, 6 Oct 2016 12:28:05 +0000 (14:28 +0200)
    - template-provider reaches out for ise-harverster
      when template not available
    - involve template-provider in ios-xe renderer (async blacking call)

Change-Id: I4f6077bbeccbaabe2e9dd7025972ef906e79dbe8
Signed-off-by: Michal Rehak <mirehak@cisco.com>
(cherry picked from commit 27a291d46621e5763e9e38986cc2ac858e4e1fb1)

16 files changed:
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImpl.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyManagerUtil.java
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImpl.java
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/SxpEpProviderProviderImplTest.java
sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/EPPolicyTemplateProviderIseImpl.java
sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/GbpIseConfigListenerImpl.java
sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/GbpIseSgtHarvester.java
sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/GbpIseSgtHarvesterImpl.java
sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/SgtInfo.java
sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/util/IseReplyUtil.java
sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/EPPolicyTemplateProviderIseImplTest.java
sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/GbpIseSgtHarvesterImplTest.java
sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/IseResourceTestHelper.java [new file with mode: 0644]
sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/util/IseReplyUtilTest.java [new file with mode: 0644]
sxp-integration/sxp-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/rawIse-allSgts1.xml [moved from sxp-integration/sxp-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/rawIse-allSgts.xml with 100% similarity]
sxp-integration/sxp-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/rawIse-allSgts2.xml [new file with mode: 0644]

index 884e74e469defdecfb9a73440552f610aeace3b5..c273613126a1bec6929e7632ed348c894ab26b64 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Create;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.DsAction.Delete;
 
+import java.util.concurrent.TimeUnit;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import java.util.List;
@@ -29,7 +30,6 @@ import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.Po
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.StatusUtil;
 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPToSgtMapper;
-import org.opendaylight.groupbasedpolicy.sxp.ep.provider.spi.SxpEpProviderProvider;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
@@ -156,12 +156,16 @@ public class PolicyManagerImpl implements PolicyManager {
                     managementIpAddress, mountpoint);
             context.setPolicyMapLocation(policyMapLocation);
 
+            // TODO: pull timeout for async ops from config
+            final long TIMEOUT = 10;
+            final TimeUnit UNIT = TimeUnit.SECONDS;
+
             final Sgt sourceSgt = PolicyManagerUtil.findSgtTag(epToSgtMapper, rendererEndpoint, dataAfter.getEndpoints()
-                    .getAddressEndpointWithLocation());
+                    .getAddressEndpointWithLocation(), TIMEOUT, UNIT);
             // Peer Endpoint
             for (PeerEndpoint peerEndpoint : rendererEndpoint.getPeerEndpoint()) {
                 final Sgt destinationSgt = PolicyManagerUtil.findSgtTag(epToSgtMapper, peerEndpoint, dataAfter.getEndpoints()
-                        .getAddressEndpointWithLocation());
+                        .getAddressEndpointWithLocation(), TIMEOUT, UNIT);
                 if (sourceSgt == null || destinationSgt == null) {
                     final String info = String.format("Endpoint-policy: missing sgt value(sourceSgt=%s, destinationSgt=%s)",
                             sourceSgt, destinationSgt);
index e9e9ee27638142b389c0defd1155929ec881750a..e81924d2c5bf068106c6d7733f9620a5ab12ab1f 100644 (file)
@@ -11,8 +11,11 @@ package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
 import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -20,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -82,7 +86,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.AddressEndpointWithLocationAug;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -200,20 +203,24 @@ public class PolicyManagerUtil {
 
     @Nullable
     public static Sgt findSgtTag(final EPToSgtMapper sxpEpProvider, final AddressEndpointKey endpointKey,
-                                 final List<AddressEndpointWithLocation> endpointsWithLocation) {
+                                 final List<AddressEndpointWithLocation> endpointsWithLocation, final long timeout, final TimeUnit unit) {
         if (endpointKey == null || endpointsWithLocation == null) {
             return null;
         }
         final AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
                 endpointsWithLocation);
 
-        //TODO: involve sxpEpProvider
-        final AddressEndpointWithLocationAug augmentation = endpointWithLocation.getAugmentation(AddressEndpointWithLocationAug.class);
-        if (augmentation == null) {
-            return null;
+        final ListenableFuture<Collection<Sgt>> sgtForEPFu = sxpEpProvider.findSgtForEP(endpointWithLocation);
+
+        Sgt sgt = null;
+        try {
+            sgt = Iterables.getFirst(sgtForEPFu.get(timeout, unit), null);
+            LOG.trace("For ep[{}] found sgt: {}", endpointKey, sgt);
+        } catch (Exception e) {
+            LOG.debug("failed to obtain sgt for given endpoint: ", e.getMessage());
         }
 
-        return augmentation.getSgt();
+        return sgt;
     }
 
     /**
index 0542cd4c37899adc2cf91d61bb4ee11c56f05740..37e754ada1e63a90137cb12bc97183ef7da9d037 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.groupbasedpolicy.api.DomainSpecificRegistry;
-import org.opendaylight.groupbasedpolicy.api.EndpointAugmentor;
 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateDaoFacade;
 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateProviderRegistry;
 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPToSgtMapper;
@@ -47,7 +46,6 @@ public class SxpEpProviderProviderImpl implements SxpEpProviderProvider {
     private final EPTemplateListener epPolicyTemplateListener;
     private final EPTemplateListener epForwardingTemplateListener;
     private final DomainSpecificRegistry domainSpecificRegistry;
-    private final EndpointAugmentor sxpEndpointAugmentor;
     private final EPPolicyTemplateProviderRegistry epPolicyTemplateRegistry;
     private final EPToSgtMapper epToSgtMapper;
 
@@ -89,10 +87,6 @@ public class SxpEpProviderProviderImpl implements SxpEpProviderProvider {
         epForwardingTemplateListener = new EPForwardingTemplateListenerImpl(dataBroker, sxpMapperReactor, epForwardingTemplateCachedDao,
                 masterDBBindingDao, epPolicyTemplateDaoFacade);
 
-        // sxp-ep-augmentor -> deprecated, will use ep2sxpMapper service
-        sxpEndpointAugmentor = new SxpEndpointAugmentorImpl(epPolicyTemplateDao, epPolicyTemplateKeyFactory);
-        domainSpecificRegistry.getEndpointAugmentorRegistry().register(sxpEndpointAugmentor);
-
         LOG.info("started SxmMapper");
     }
 
@@ -112,6 +106,5 @@ public class SxpEpProviderProviderImpl implements SxpEpProviderProvider {
         epPolicyTemplateListener.close();
         epForwardingTemplateListener.close();
         epPolicyTemplateRegistry.close();
-        domainSpecificRegistry.getEndpointAugmentorRegistry().unregister(sxpEndpointAugmentor);
     }
 }
index 8039fcf9d0c97eeaa08eff72956230b413a8448d..6d5c1123c386630eee5daf5795c54a41c133b166 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl;
 
+import static org.powermock.api.mockito.PowerMockito.verifyNew;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
 import com.google.common.collect.Ordering;
 import org.junit.Assert;
 import org.junit.Before;
@@ -40,11 +45,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.mast
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
-import static org.powermock.api.mockito.PowerMockito.verifyNew;
-import static org.powermock.api.mockito.PowerMockito.whenNew;
-import static org.powermock.api.support.membermodification.MemberMatcher.method;
-import static org.powermock.api.support.membermodification.MemberModifier.stub;
-
 /**
  * Test for {@link SxpEpProviderProviderImpl}.
  */
@@ -103,8 +103,6 @@ public class SxpEpProviderProviderImplTest {
 
     @Before
     public void setUp() throws Exception {
-        Mockito.when(domainSpecificRegistry.getEndpointAugmentorRegistry()).thenReturn(epAugmentorRegistry);
-
         whenNew(EPPolicyTemplateProviderRegistryImpl.class).withNoArguments().thenReturn(templateProviderRegistry);
         whenNew(SxpMapperReactorImpl.class).withArguments(endpointService, dataBroker).thenReturn(sxpMapperReactor);
         whenNew(SimpleCachedDaoImpl.class).withNoArguments().thenReturn(epPolicyTemplateCachedDao, masterDBBindingCachedDao);
@@ -137,7 +135,6 @@ public class SxpEpProviderProviderImplTest {
         provider = new SxpEpProviderProviderImpl(dataBroker, endpointService, domainSpecificRegistry, sgtGeneratorConfig);
 
         Mockito.verify(templateProviderRegistry).addDistributionTarget(epPolicyTemplateDaoFacade);
-        Mockito.verify(epAugmentorRegistry).register(sxpEPAugmentor);
 
         // check if all expected object got constructed and wired
         verifyNew(EPPolicyTemplateProviderRegistryImpl.class).withNoArguments();
@@ -157,7 +154,6 @@ public class SxpEpProviderProviderImplTest {
                 masterDBBindingDao, epForwardingTemplateDao);
         verifyNew(EPForwardingTemplateListenerImpl.class).withArguments(dataBroker, sxpMapperReactor, epFwTemplateCachedDao,
                 masterDBBindingDao, epPolicyTemplateDaoFacade);
-        verifyNew(SxpEndpointAugmentorImpl.class).withArguments(epPolicyTemplateDao, epPolicyTemplateKeyFactory);
     }
 
     @Test
@@ -172,6 +168,5 @@ public class SxpEpProviderProviderImplTest {
         Mockito.verify(epPolicyTemplateListener).close();
         Mockito.verify(epForwardingTemplateListener).close();
         Mockito.verify(templateProviderRegistry).close();
-        Mockito.verify(epAugmentorRegistry).unregister(sxpEPAugmentor);
     }
 }
\ No newline at end of file
index bcea610d4dcd66b7ebacf2c34a8cf789de59e559..7497bc000e84d353dd0dce43596781dec38521d2 100644 (file)
@@ -67,7 +67,7 @@ public class EPPolicyTemplateProviderIseImpl implements EPPolicyTemplateProvider
     }
 
     private ListenableFuture<Optional<String>> queryIseOnSgt(final IseContext iseContext, @Nonnull final Sgt sgt) {
-        final ListenableFuture<Collection<SgtInfo>> sgtUpdateFu = iseSgtHarvester.update(iseContext);
+        final ListenableFuture<Collection<SgtInfo>> sgtUpdateFu = iseSgtHarvester.harvestAll(iseContext);
         return Futures.transform(sgtUpdateFu, new Function<Collection<SgtInfo>, Optional<String>>() {
             @Nullable
             @Override
index 031f9bfd6d86e916ca3bb843c22b27f6c71310d9..92e84100b9e9086f1c97c0348cd3e9d8ed2959c0 100644 (file)
@@ -73,7 +73,6 @@ public class GbpIseConfigListenerImpl implements GbpIseConfigListener {
     public void onDataTreeChanged(@Nonnull final Collection<DataTreeModification<IseSourceConfig>> collection) {
         for (DataTreeModification<IseSourceConfig> modification : collection) {
             final IseSourceConfig iseSourceConfig = modification.getRootNode().getDataAfter();
-            //TODO: separate template provider from harvesting
             final IseContext iseContext = new IseContext(iseSourceConfig);
             templateProviderFacade.assignIseContext(iseContext);
             if (iseSourceConfig != null) {
index 9cecd622e7a7b1795038b3374b39558b06b55be3..617da2b5a9acba7a4b4b017372d402b94f542927 100644 (file)
@@ -22,10 +22,4 @@ public interface GbpIseSgtHarvester {
      * @return retrieved and stored sgts
      */
     ListenableFuture<Collection<SgtInfo>> harvestAll(@Nonnull IseContext iseContext);
-
-    /**
-     * @param iseContext user given ise info
-     * @return retrieved and stored sgts
-     */
-    ListenableFuture<Collection<SgtInfo>> update(@Nonnull IseContext iseContext);
 }
index 74dee902638adf5da3301baf2845b69acf389bde..ef93ebab92a8c8144f247f29aa20381de50cd40c 100644 (file)
@@ -16,9 +16,11 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import com.sun.jersey.api.client.Client;
 import com.sun.jersey.api.client.WebResource;
 import java.net.URI;
+import java.security.GeneralSecurityException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
@@ -29,7 +31,6 @@ import java.util.stream.Collectors;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpressionException;
 import org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.util.IseReplyUtil;
 import org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.util.RestClientFactory;
@@ -61,18 +62,17 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
 
     @Override
     public ListenableFuture<Collection<SgtInfo>> harvestAll(@Nonnull final IseContext iseContext) {
-        final IseSourceConfig iseSourceConfig = iseContext.getIseSourceConfig();
-        final ConnectionConfig connectionConfig = iseSourceConfig.getConnectionConfig();
         ListenableFuture<Collection<SgtInfo>> result;
         try {
-            final Client iseClient = RestClientFactory.createIseClient(connectionConfig);
-            final WebResource baseWebResource = iseClient.resource(connectionConfig.getIseRestUrl().getValue());
+            final IseSourceConfig iseSourceConfig = iseContext.getIseSourceConfig();
+            final ConnectionConfig connectionConfig = iseSourceConfig.getConnectionConfig();
+            final WebResource baseWebResource = createWebResource(connectionConfig);
 
             final WebResource.Builder requestBuilder = RestClientFactory.createRequestBuilder(baseWebResource,
                     connectionConfig.getHeader(), RestClientFactory.PATH_ERS_CONFIG_SGT);
             final String rawSgtSummary = IseReplyUtil.deliverResponse(requestBuilder);
 
-            final List<SgtInfo> sgtInfos = harvestDetails(rawSgtSummary, baseWebResource, connectionConfig.getHeader());
+            final List<SgtInfo> sgtInfos = harvestDetails(rawSgtSummary, baseWebResource, connectionConfig, iseContext.getUuidToSgtMap());
 
             ListenableFuture<Void> processingResult = Futures.immediateCheckedFuture(null);
             for (SgtInfoProcessor processor : sgtInfoProcessors) {
@@ -88,6 +88,11 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
                 @Nullable
                 @Override
                 public Collection<SgtInfo> apply(@Nullable final Void input) {
+                    // update uuid map
+                    for (SgtInfo sgtInfo : sgtInfos) {
+                        iseContext.getUuidToSgtMap().put(sgtInfo.getUuid(), sgtInfo.getSgt().getValue());
+                    }
+                    //TODO: store harvest stats to DS/operational
                     // always success, otherwise there will be TransactionCommitFailedException thrown
                     return sgtInfos;
                 }
@@ -100,7 +105,13 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
         return result;
     }
 
-    private List<SgtInfo> harvestDetails(final String rawSgtSummary, final WebResource baseWebResource, final List<Header> headers) {
+    private WebResource createWebResource(final ConnectionConfig connectionConfig) throws GeneralSecurityException {
+        final Client iseClient = RestClientFactory.createIseClient(connectionConfig);
+        return iseClient.resource(connectionConfig.getIseRestUrl().getValue());
+    }
+
+    private List<SgtInfo> harvestDetails(final String rawSgtSummary, final WebResource baseWebResource,
+                                         final ConnectionConfig connectionConfig, final Map<String, Integer> uuidToSgtMap) {
         LOG.trace("rawSgtSummary: {}", rawSgtSummary);
         final List<Future<SgtInfo>> sgtInfoFutureBag = new ArrayList<>();
 
@@ -111,22 +122,24 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
         // parse sgtSummary
         final XPath xpath = IseReplyUtil.setupXpath();
 
-        InputSource inputSource = IseReplyUtil.createInputSource(rawSgtSummary);
+        final InputSource inputSource = IseReplyUtil.createInputSource(rawSgtSummary);
         try {
-            final NodeList sgtLinkNodes = (NodeList) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_ALL_LINK_HREFS, inputSource,
-                    XPathConstants.NODESET);
-            for (int i = 0; i < sgtLinkNodes.getLength(); i++) {
-                final String sgtLinkHrefValue = sgtLinkNodes.item(i).getNodeValue();
-                LOG.debug("found sgt resource [{}]: {}", i, sgtLinkHrefValue);
+            final NodeList sgtResources = IseReplyUtil.findAllSgtResourceNodes(xpath, inputSource);
+            final Collection<Node> sgtLinkNodes = IseReplyUtil.filterNewResourcesByID(uuidToSgtMap, xpath, sgtResources);
+
+            int counter = 0;
+            for (Node sgtLinkNode : sgtLinkNodes) {
+                final String sgtLinkHrefValue = sgtLinkNode.getNodeValue();
+                LOG.debug("found sgt resource: {}", sgtLinkHrefValue);
 
                 // submit all query tasks to pool
-                final int idx = i;
+                final int idx = counter++;
                 sgtInfoFutureBag.add(pool.submit(new Callable<SgtInfo>() {
                     @Override
                     public SgtInfo call() {
                         SgtInfo sgtInfo = null;
                         try {
-                            sgtInfo = querySgtDetail(baseWebResource, headers, xpath, idx, sgtLinkHrefValue);
+                            sgtInfo = querySgtDetail(baseWebResource, connectionConfig.getHeader(), xpath, idx, sgtLinkHrefValue);
                         } catch (XPathExpressionException e) {
                             LOG.info("failed to parse sgt response for {}: {}", sgtLinkHrefValue, e.getMessage());
                         }
@@ -169,17 +182,17 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
                                    final int idx, final String sgtLinkHrefValue) throws XPathExpressionException {
         // query all sgt entries (serial-vise)
         final URI hrefToSgtDetailUri = URI.create(sgtLinkHrefValue);
-        final WebResource.Builder requestBuilder = RestClientFactory.createRequestBuilder(baseWebResource, headers, hrefToSgtDetailUri.getPath());
+        final WebResource.Builder requestBuilder = RestClientFactory.createRequestBuilder(baseWebResource, headers,
+                hrefToSgtDetailUri.getPath());
         // time consuming operation - wait for rest response
         final String rawSgtDetail = IseReplyUtil.deliverResponse(requestBuilder);
         LOG.trace("rawSgtDetail: {}", rawSgtDetail);
 
         // process response xml
-        final Node sgtNode = (Node) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_DETAIL, IseReplyUtil.createInputSource(rawSgtDetail),
-                XPathConstants.NODE);
-        final Node sgtName = (Node) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_NAME_ATTR, sgtNode, XPathConstants.NODE);
-        final Node sgtUuid = (Node) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_UUID_ATTR, sgtNode, XPathConstants.NODE);
-        final Node sgtValue = (Node) xpath.evaluate(IseReplyUtil.EXPRESSION_SGT_VALUE, sgtNode, XPathConstants.NODE);
+        final Node sgtNode = IseReplyUtil.findSgtDetailNode(xpath, rawSgtDetail);
+        final Node sgtName = IseReplyUtil.gainSgtName(xpath, sgtNode);
+        final Node sgtUuid = IseReplyUtil.gainSgtUuid(xpath, sgtNode);
+        final Node sgtValue = IseReplyUtil.gainSgtValue(xpath, sgtNode);
         LOG.debug("sgt value [{}]: {} -> {}", idx, sgtValue, sgtName);
 
         // store replies into list of SgtInfo
@@ -187,9 +200,4 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
         return new SgtInfo(sgt, sgtName.getNodeValue(), sgtUuid.getNodeValue());
     }
 
-    @Override
-    public ListenableFuture<Collection<SgtInfo>> update(@Nonnull final IseContext iseContext) {
-        //TODO: stub
-        return null;
-    }
 }
index 173a593403ac55fcbe42ba9bddb74d7e6ef881be..8cb4921b94625fb5a3f0a0e8565b611b3f06dea7 100644 (file)
@@ -45,4 +45,11 @@ public class SgtInfo {
     public String getName() {
         return name;
     }
+
+    /**
+     * @return uuid of sgt
+     */
+    public String getUuid() {
+        return uuid;
+    }
 }
index 3861765f25ba0705bc8252d1cec79530e26fd9b3..930082bd014ea941f6758c8799148b82711336ef 100644 (file)
@@ -11,11 +11,18 @@ package org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.util;
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.WebResource;
 import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
+import java.util.Map;
 import javax.xml.XMLConstants;
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
 /**
@@ -23,11 +30,12 @@ import org.xml.sax.InputSource;
  */
 public class IseReplyUtil {
 
-    public static final String EXPRESSION_SGT_ALL_LINK_HREFS = "/ns3:searchResult/ns3:resources/ns5:resource/link/@href";
-    public static final String EXPRESSION_SGT_DETAIL = "./ns4:sgt";
-    public static final String EXPRESSION_SGT_NAME_ATTR = "./@name";
-    public static final String EXPRESSION_SGT_UUID_ATTR = "./@id";
-    public static final String EXPRESSION_SGT_VALUE = "./value/text()";
+    private static final String EXPRESSION_SGT_ALL_RESOURCES = "/ns3:searchResult/ns3:resources/ns5:resource";
+    private static final String EXPRESSION_SGT_DETAIL_LINK = "./link/@href";
+    private static final String EXPRESSION_SGT_DETAIL = "./ns4:sgt";
+    private static final String EXPRESSION_SGT_NAME_ATTR = "./@name";
+    private static final String EXPRESSION_SGT_UUID_ATTR = "./@id";
+    private static final String EXPRESSION_SGT_VALUE = "./value/text()";
 
     private IseReplyUtil() {
         throw new IllegalAccessError("util class - no instances supported");
@@ -80,4 +88,48 @@ public class IseReplyUtil {
     public static InputSource createInputSource(final String rawSgtDetail) {
         return new InputSource(new StringReader(rawSgtDetail));
     }
+
+    /**
+     * @param uuidToSgtMap map of existing sgts (by uuid)
+     * @param xpath        xpath instance
+     * @param sgtResources input node list
+     * @return new/unknown sgts to explore
+     * @throws XPathExpressionException in case xpath processing fails
+     */
+    public static Collection<Node> filterNewResourcesByID(final Map<String, Integer> uuidToSgtMap, final XPath xpath,
+                                                          final NodeList sgtResources)
+            throws XPathExpressionException {
+        final Collection<Node> nodesToExplore = new ArrayList<>();
+        for (int i = 0; i < sgtResources.getLength(); i++) {
+            final String uuid = ((Node) xpath.evaluate(EXPRESSION_SGT_UUID_ATTR, sgtResources.item(i), XPathConstants.NODE)).getNodeValue();
+            if (!uuidToSgtMap.containsKey(uuid)) {
+                nodesToExplore.add(
+                        (Node) xpath.evaluate(EXPRESSION_SGT_DETAIL_LINK, sgtResources.item(i), XPathConstants.NODE)
+                );
+            }
+        }
+        return nodesToExplore;
+    }
+
+    public static NodeList findAllSgtResourceNodes(final XPath xpath, final InputSource inputSource) throws XPathExpressionException {
+        return (NodeList) xpath.evaluate(EXPRESSION_SGT_ALL_RESOURCES, inputSource,
+                XPathConstants.NODESET);
+    }
+
+    public static Node gainSgtValue(final XPath xpath, final Node sgtNode) throws XPathExpressionException {
+        return (Node) xpath.evaluate(EXPRESSION_SGT_VALUE, sgtNode, XPathConstants.NODE);
+    }
+
+    public static Node gainSgtUuid(final XPath xpath, final Node sgtNode) throws XPathExpressionException {
+        return (Node) xpath.evaluate(EXPRESSION_SGT_UUID_ATTR, sgtNode, XPathConstants.NODE);
+    }
+
+    public static Node gainSgtName(final XPath xpath, final Node sgtNode) throws XPathExpressionException {
+        return (Node) xpath.evaluate(EXPRESSION_SGT_NAME_ATTR, sgtNode, XPathConstants.NODE);
+    }
+
+    public static Node findSgtDetailNode(final XPath xpath, final String rawSgtDetail) throws XPathExpressionException {
+        return (Node) xpath.evaluate(EXPRESSION_SGT_DETAIL, createInputSource(rawSgtDetail),
+                XPathConstants.NODE);
+    }
 }
index 126ee61eb89a768b40a5210459747ad360822180..b934a43af195075648bf5a934101217c07838272 100644 (file)
@@ -31,13 +31,13 @@ import org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.util.IseReplyUtil;
 import org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.util.RestClientFactory;
 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.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.TemplateGenerated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.IseSourceConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.IseSourceConfigBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.ise.source.config.ConnectionConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.ise.source.config.ConnectionConfigBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ise.adapter.model.rev160630.gbp.sxp.ise.adapter.ise.source.config.connection.config.HeaderBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.TemplateGenerated;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgt;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
@@ -112,12 +112,13 @@ public class EPPolicyTemplateProviderIseImplTest {
         final String epgName = SGT_INFO.getName();
         final Node sgtNameNode = Mockito.mock(Node.class);
         Mockito.when(sgtNameNode.getNodeValue()).thenReturn(epgName);
-        Mockito.when(xpathWalker.evaluate(Matchers.same(IseReplyUtil.EXPRESSION_SGT_NAME_ATTR),
+        // matching value of IseReplyUtil.EXPRESSION_SGT_NAME_ATTR
+        Mockito.when(xpathWalker.evaluate(Matchers.same("./@name"),
                 Matchers.<InputSource>any(), Matchers.same(XPathConstants.NODE)))
                 .thenReturn(sgtNameNode);
 
         Mockito.when(iseContext.getIseSourceConfig()).thenReturn(sourceConfig);
-        Mockito.when(iseSgtHarvester.update(iseContext))
+        Mockito.when(iseSgtHarvester.harvestAll(iseContext))
                 .thenReturn(Futures.immediateFuture(Collections.singletonList(SGT_INFO)));
 
         templateProvider.assignIseContext(iseContext);
index 8c3c365a5172dbea8a9cdb44c1327d191a436edd..b63763864b39c7f724add43a9c05b42f63104207 100644 (file)
@@ -16,10 +16,7 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.sun.jersey.api.client.Client;
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.WebResource;
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -75,22 +72,8 @@ public class GbpIseSgtHarvesterImplTest {
     private GbpIseSgtHarvesterImpl harvester;
 
     public GbpIseSgtHarvesterImplTest() throws IOException {
-        iseReplyAllSgts = readLocalResource("./rawIse-allSgts.xml");
-        iseReplySgtDetail = readLocalResource("./rawIse-sgtDetail.xml");
-    }
-
-    private static String readLocalResource(final String resourcePath) throws IOException {
-        final StringBuilder collector = new StringBuilder();
-        try (
-                final InputStream iseReplySource = GbpIseSgtHarvesterImplTest.class.getResourceAsStream(resourcePath);
-                final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(iseReplySource))
-        ) {
-            String line;
-            while ((line = bufferedReader.readLine()) != null) {
-                collector.append(line);
-            }
-        }
-        return collector.toString();
+        iseReplyAllSgts = IseResourceTestHelper.readLocalResource("./rawIse-allSgts1.xml");
+        iseReplySgtDetail = IseResourceTestHelper.readLocalResource("./rawIse-sgtDetail.xml");
     }
 
     @Before
@@ -125,6 +108,7 @@ public class GbpIseSgtHarvesterImplTest {
                 Futures.immediateCheckedFuture(null));
 
         final ListenableFuture<Collection<SgtInfo>> harvestResult = harvester.harvestAll(iseContext);
+        final Collection<SgtInfo> addedSgts = harvestResult.get(2, TimeUnit.SECONDS);
 
         final InOrder inOrder = Mockito.inOrder(client, webResource, builder);
         inOrder.verify(client).resource(ISE_REST_URL.getValue());
@@ -140,7 +124,6 @@ public class GbpIseSgtHarvesterImplTest {
         inOrder.verify(builder).get(ClientResponse.class);
         inOrder.verifyNoMoreInteractions();
 
-        final Collection<SgtInfo> count = harvestResult.get(2, TimeUnit.SECONDS);
-        Assert.assertEquals(1, count.size());
+        Assert.assertEquals(1, addedSgts.size());
     }
 }
\ No newline at end of file
diff --git a/sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/IseResourceTestHelper.java b/sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/IseResourceTestHelper.java
new file mode 100644 (file)
index 0000000..505f750
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.groupbasedpolicy.sxp_ise_adapter.impl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * Purpose: read content of given test file
+ */
+public class IseResourceTestHelper {
+    public static String readLocalResource(final String resourcePath) throws IOException {
+        final StringBuilder collector = new StringBuilder();
+        try (
+                final InputStream iseReplySource = IseResourceTestHelper.class.getResourceAsStream(resourcePath);
+                final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(iseReplySource))
+        ) {
+            String line;
+            while ((line = bufferedReader.readLine()) != null) {
+                collector.append(line);
+            }
+        }
+        return collector.toString();
+    }
+}
diff --git a/sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/util/IseReplyUtilTest.java b/sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/util/IseReplyUtilTest.java
new file mode 100644 (file)
index 0000000..9e3af65
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. 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.groupbasedpolicy.sxp_ise_adapter.impl.util;
+
+import static org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl.IseResourceTestHelper.readLocalResource;
+
+import com.google.common.collect.Iterables;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.xpath.XPath;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * Test for {@link IseReplyUtil}.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class IseReplyUtilTest {
+
+    private final String iseReplyAllSgts;
+    private XPath xpath;
+
+    public IseReplyUtilTest() throws IOException {
+        iseReplyAllSgts = readLocalResource("./rawIse-allSgts2.xml");
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        xpath = IseReplyUtil.setupXpath();
+    }
+
+    @Test
+    public void filterNewResourcesByID() throws Exception {
+        final Map<String, Integer> uuidMap = new HashMap<>();
+        uuidMap.put("abc123", 42);
+
+        final InputSource inputSource = IseReplyUtil.createInputSource(iseReplyAllSgts);
+        final NodeList allSgtResourceNodes = IseReplyUtil.findAllSgtResourceNodes(xpath, inputSource);
+
+        final Collection<Node> filteredNodes = IseReplyUtil.filterNewResourcesByID(uuidMap, xpath, allSgtResourceNodes);
+
+        Assert.assertEquals(1, filteredNodes.size());
+        Assert.assertEquals("https://example.org:9060/ers/config/sgt/abc124", Iterables.getFirst(filteredNodes, null).getNodeValue());
+    }
+}
\ No newline at end of file
diff --git a/sxp-integration/sxp-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/rawIse-allSgts2.xml b/sxp-integration/sxp-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/rawIse-allSgts2.xml
new file mode 100644 (file)
index 0000000..57475e3
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+  ~ Copyright (c) 2016 Cisco Systems, Inc. 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
+  -->
+
+<ns3:searchResult xmlns:ns5="ers.ise.cisco.com"
+                  xmlns:ns3="v2.ers.ise.cisco.com"
+                  total="1">
+    <ns3:nextPage rel="next" href="" type="application/xml"/>
+    <ns3:resources>
+        <ns5:resource description="" id="abc123" name="boss_group">
+            <link rel="self" href="https://example.org:9060/ers/config/sgt/abc123" type="application/xml"/>
+        </ns5:resource>
+        <ns5:resource description="" id="abc124" name="worker_group">
+            <link rel="self" href="https://example.org:9060/ers/config/sgt/abc124" type="application/xml"/>
+        </ns5:resource>
+    </ns3:resources>
+</ns3:searchResult>