BUG-6858: adapt to ise api, change lookup from ise 12/46612/1
authorMichal Rehak <mirehak@cisco.com>
Fri, 30 Sep 2016 07:43:22 +0000 (09:43 +0200)
committerMichal Rehak <mirehak@cisco.com>
Thu, 6 Oct 2016 12:28:05 +0000 (14:28 +0200)
 - lookup from ise now updates sgt
 - enhance sgtInfo by uuid
 - use uuid to detect new sgts

Change-Id: I2542b50a3c3735378dd170864ff227f4c471c363
Signed-off-by: Michal Rehak <mirehak@cisco.com>
(cherry picked from commit 4adb237ca9080a70c76f996fcefcbba2c3677124)

17 files changed:
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/api/EPPolicyTemplateProvider.java
sxp-integration/sxp-ep-provider/src/main/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoFacadeImpl.java
sxp-integration/sxp-ep-provider/src/test/java/org/opendaylight/groupbasedpolicy/sxp/ep/provider/impl/dao/EPPolicyTemplateDaoFacadeImplTest.java
sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/EPPolicyTemplateProviderFacade.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/GbpIseAdapterProvider.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/IseContext.java [new file with mode: 0644]
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/GbpIseConfigListenerImplTest.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/SgtToEPTemplateGeneratorImplTest.java
sxp-integration/sxp-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/SgtToEpgGeneratorImplTest.java

index 00f59b5d720c4374dbef52f88bda9177710e930d..4955b56e540f74bba81b791f685c3bdcc7f6c208 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.groupbasedpolicy.sxp.ep.provider.api;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.Optional;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
@@ -23,5 +24,5 @@ public interface EPPolicyTemplateProvider {
      * @param sgt of template
      * @return template if available (expecting empty conditions field)
      */
-    Optional<EndpointPolicyTemplateBySgt> provideTemplate(@Nonnull final Sgt sgt);
+    ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> provideTemplate(@Nonnull final Sgt sgt);
 }
index fa3f457c11d0632605b67eb1188db8e6586e865c..72e7e87fc987a85d79563ad94bc8269c26a96865 100644 (file)
@@ -24,12 +24,6 @@ import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateDao
 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.api.EPPolicyTemplateProvider;
 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SgtGeneratorImpl;
 import org.opendaylight.groupbasedpolicy.sxp.ep.provider.impl.SimpleCachedDao;
-import org.opendaylight.groupbasedpolicy.util.IidFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroupBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ep.provider.model.rev160302.SxpEpMapper;
 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;
@@ -83,52 +77,27 @@ public class EPPolicyTemplateDaoFacadeImpl implements EPPolicyTemplateDaoFacade
                 return templateOpt.transform(template -> Futures.immediateFuture(templateOpt))
                         // failed to read template -> invoke fallback if available
                         .or(() -> java.util.Optional.ofNullable(templateProvider)
-                                .flatMap(provider -> templateProvider.provideTemplate(key))
-                                .map(template -> storeTemplateAndEpg(template))
+                                .map(provider -> templateProvider.provideTemplate(key))
+                                .map(template -> rewrapOptionalToGuavaOptional(template))
                                 .orElse(Futures.immediateFuture(Optional.absent()))
                         );
             }
         });
     }
 
-    private ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> storeTemplateAndEpg(final EndpointPolicyTemplateBySgt template) {
-        // store EPG (presume that it does not exist)
-        final Sgt sgtValue = template.getSgt();
-        LOG.trace("storing EPGs for generated epPolicyTemplate: {} [{}]",
-                sgtValue.getValue(), template.getEndpointGroups().size());
-        final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
-
-        boolean createParent = true;
-        for (EndpointGroupId epgId : template.getEndpointGroups()) {
-            final InstanceIdentifier<EndpointGroup> epgPath = IidFactory.endpointGroupIid(template.getTenant(), epgId);
-            final EndpointGroup epg = new EndpointGroupBuilder()
-                    .setId(epgId)
-                    .setDescription(new Description("imported from ISE for sgt=" + sgtValue.getValue()))
-                    .setName(new Name(String.format("%s_ISE_SGT_%d", epgId.getValue(), sgtValue.getValue())))
-                    .build();
-            wTx.put(LogicalDatastoreType.CONFIGURATION, epgPath, epg, createParent);
-            createParent = false;
-        }
-
-        // store ep-policy-template
-        LOG.trace("storing generated epPolicyTemplate: {}", sgtValue.getValue());
-        final InstanceIdentifier<EndpointPolicyTemplateBySgt> epPolicyTemplatePath = InstanceIdentifier
-                .create(SxpEpMapper.class)
-                .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(sgtValue));
-        wTx.put(LogicalDatastoreType.CONFIGURATION, epPolicyTemplatePath, template, true);
-
-        return Futures.transform(wTx.submit(), createStoreOutcomeHandlerToOptional(template));
+    private <T> ListenableFuture<Optional<T>> rewrapOptionalToGuavaOptional(final ListenableFuture<java.util.Optional<T>> templateFu) {
+        return Futures.transform(templateFu, new Function<java.util.Optional<T>, Optional<T>>() {
+                    @Nullable
+                    @Override
+                    public Optional<T> apply(@Nullable final java.util.Optional<T> input) {
+                        return java.util.Optional.ofNullable(input)
+                                .map(origNonnullInput -> Optional.fromNullable(origNonnullInput.orElse(null)))
+                                .orElse(Optional.absent());
+                    }
+                }
+        );
     }
 
-    private Function<Void, Optional<EndpointPolicyTemplateBySgt>> createStoreOutcomeHandlerToOptional(final EndpointPolicyTemplateBySgt template) {
-        return new Function<Void, Optional<EndpointPolicyTemplateBySgt>>() {
-            @Nullable
-            @Override
-            public Optional<EndpointPolicyTemplateBySgt> apply(@Nullable final Void aVoid) {
-                return Optional.of(template);
-            }
-        };
-    }
 
     private Function<Void, Collection<EndpointPolicyTemplateBySgt>> createStoreOutcomeHandlerToCollection(final EndpointPolicyTemplateBySgt template) {
         return new Function<Void, Collection<EndpointPolicyTemplateBySgt>>() {
index 532da14ddb16a9140a3f22bb6020c28e5a2c3b67..9150b9f646acde71815eb18e5c7b4da5aa44584e 100644 (file)
@@ -101,7 +101,7 @@ public class EPPolicyTemplateDaoFacadeImplTest {
                 .build();
 
         Mockito.when(delegateDao.read(SGT)).thenReturn(Futures.immediateFuture(Optional.absent()));
-        Mockito.when(provider.provideTemplate(SGT)).thenReturn(java.util.Optional.of(template));
+        Mockito.when(provider.provideTemplate(SGT)).thenReturn(Futures.immediateFuture(java.util.Optional.of(template)));
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
         facade.setTemplateProvider(provider);
 
@@ -124,7 +124,7 @@ public class EPPolicyTemplateDaoFacadeImplTest {
     @Test
     public void testRead_failProviderMiss() throws Exception {
         Mockito.when(delegateDao.read(SGT)).thenReturn(Futures.immediateFuture(Optional.absent()));
-        Mockito.when(provider.provideTemplate(SGT)).thenReturn(java.util.Optional.empty());
+        Mockito.when(provider.provideTemplate(SGT)).thenReturn(Futures.immediateFuture(java.util.Optional.empty()));
         facade.setTemplateProvider(provider);
 
 
@@ -141,8 +141,7 @@ public class EPPolicyTemplateDaoFacadeImplTest {
                 .build();
 
         Mockito.when(delegateDao.read(SGT)).thenReturn(Futures.immediateFuture(Optional.absent()));
-        Mockito.when(provider.provideTemplate(SGT)).thenReturn(java.util.Optional.of(template));
-        Mockito.when(wTx.submit()).thenReturn(Futures.immediateFailedCheckedFuture(TX_EXCEPTION));
+        Mockito.when(provider.provideTemplate(SGT)).thenReturn(Futures.immediateFailedCheckedFuture(TX_EXCEPTION));
         facade.setTemplateProvider(provider);
 
         final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> actual = facade.read(SGT);
index df408f37d715a1a74516747764aa876f2f54a8e1..e330f7be4fefd1ee9363003acf95682c58faa78c 100644 (file)
@@ -17,8 +17,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 public interface EPPolicyTemplateProviderFacade extends EPPolicyTemplateProvider {
 
     /**
-     * @param iseSourceConfig current ise configuration
+     * @param iseContext current ise configuration
      */
-    void assignIseSourceConfig(final IseSourceConfig iseSourceConfig);
+    void assignIseContext(final IseContext iseContext);
+
+    /**
+     * @param iseSgtHarvester stateless ise harvester
+     */
+    void setIseSgtHarvester(final GbpIseSgtHarvester iseSgtHarvester);
 
 }
index 1f8c5be4167a6007f6c24f388019f364bf981f4f..bcea610d4dcd66b7ebacf2c34a8cf789de59e559 100644 (file)
@@ -8,28 +8,23 @@
 
 package org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl;
 
+import com.google.common.base.Function;
 import com.google.common.collect.Range;
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.WebResource;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Optional;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-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.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 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.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.ise.source.config.ConnectionConfig;
 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.ep.provider.model.rev160302.sxp.ep.mapper.EndpointPolicyTemplateBySgtBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Node;
 
 /**
  * Purpose: query ise in order to get name of sgt for given tenant and build {@link EndpointPolicyTemplateBySgt}
@@ -38,13 +33,26 @@ public class EPPolicyTemplateProviderIseImpl implements EPPolicyTemplateProvider
 
     private static final Logger LOG = LoggerFactory.getLogger(EPPolicyTemplateProviderIseImpl.class);
 
-    private Optional<IseSourceConfig> iseSourceConfig = Optional.empty();
+    private Optional<IseContext> iseContext = Optional.empty();
+    private GbpIseSgtHarvester iseSgtHarvester;
 
     @Override
-    public Optional<EndpointPolicyTemplateBySgt> provideTemplate(@Nonnull final Sgt sgt) {
+    public ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> provideTemplate(@Nonnull final Sgt sgt) {
         return findIseSourceConfigBySgt(sgt)
-                .flatMap(iseSourceConfig -> queryIseOnSgt(iseSourceConfig.getConnectionConfig(), sgt)
-                        .map(sgtName -> buildTemplate(sgt, iseSourceConfig.getTenant(), sgtName)));
+                .map(iseContext -> queryIseAndBuildTemplate(iseContext, sgt))
+                .orElse(Futures.immediateFuture(Optional.empty()));
+    }
+
+    private ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> queryIseAndBuildTemplate(final IseContext iseContext, final Sgt sgt) {
+        final ListenableFuture<Optional<String>> sgtNameFu = queryIseOnSgt(iseContext, sgt);
+        return Futures.transform(sgtNameFu, new Function<Optional<String>, Optional<EndpointPolicyTemplateBySgt>>() {
+            @Nullable
+            @Override
+            public Optional<EndpointPolicyTemplateBySgt> apply(@Nullable final Optional<String> input) {
+                return Optional.ofNullable(input)
+                        .flatMap(i -> i.map(sgtName -> buildTemplate(sgt, iseContext.getIseSourceConfig().getTenant(), sgtName)));
+            }
+        });
     }
 
     private EndpointPolicyTemplateBySgt buildTemplate(final @Nonnull Sgt sgt, final @Nonnull TenantId tenantId,
@@ -58,39 +66,38 @@ public class EPPolicyTemplateProviderIseImpl implements EPPolicyTemplateProvider
                 .build();
     }
 
-    private Optional<String> queryIseOnSgt(final ConnectionConfig connectionConfig, final Sgt sgt) {
-        String sgtName = null;
-        try {
-            final Client iseClient = RestClientFactory.createIseClient(connectionConfig);
-            final WebResource baseWebResource = iseClient.resource(connectionConfig.getIseRestUrl().getValue());
-
-            final String pathToSgtDetail = String.format("%s/%d", RestClientFactory.PATH_ERS_CONFIG_SGT, sgt.getValue());
-            final WebResource.Builder requestBuilder = RestClientFactory.createRequestBuilder(baseWebResource,
-                    connectionConfig.getHeader(), pathToSgtDetail);
-            final String rawSgtDetail = IseReplyUtil.deliverResponse(requestBuilder);
+    private ListenableFuture<Optional<String>> queryIseOnSgt(final IseContext iseContext, @Nonnull final Sgt sgt) {
+        final ListenableFuture<Collection<SgtInfo>> sgtUpdateFu = iseSgtHarvester.update(iseContext);
+        return Futures.transform(sgtUpdateFu, new Function<Collection<SgtInfo>, Optional<String>>() {
+            @Nullable
+            @Override
+            public Optional<String> apply(@Nullable final Collection<SgtInfo> input) {
+                // pick first sgtInfo which equals to given sgt
+                return Optional.ofNullable(input)
+                        .flatMap(safeInput -> safeInput.stream()
+                                .filter(sgtInfo -> sgt.equals(sgtInfo.getSgt())).findFirst()
+                                .map(SgtInfo::getName));
+            }
+        });
+    }
 
-            final XPath xpath = IseReplyUtil.setupXpath();
-            final Node sgtNameNode = (Node) xpath.evaluate(
-                    IseReplyUtil.EXPRESSION_SGT_NAME_ATTR, IseReplyUtil.createInputSource(rawSgtDetail),
-                    XPathConstants.NODE);
-            sgtName = sgtNameNode.getNodeValue();
-            LOG.debug("obtained sgt/name: {}/{}", sgt.getValue(), sgtName);
-        } catch (Exception e) {
-            LOG.debug("failed to read sgt detail on ISE", e);
-        }
-        return Optional.ofNullable(sgtName);
+    private Optional<IseContext> findIseSourceConfigBySgt(final Sgt sgt) {
+        // expected relation (ise : tenant) == (1:1)
+        return iseContext
+                .filter(context ->
+                        Range.closed(context.getIseSourceConfig().getSgtRangeMin().getValue(),
+                                context.getIseSourceConfig().getSgtRangeMax().getValue())
+                                .contains(sgt.getValue())
+                );
     }
 
-    private Optional<IseSourceConfig> findIseSourceConfigBySgt(final Sgt sgt) {
-        //TODO: cover multiple sources / tenants .. lookup (option: multiple servers per tenant?)
-        return iseSourceConfig
-                .filter(config ->
-                        Range.closed(config.getSgtRangeMin().getValue(), config.getSgtRangeMax().getValue())
-                                .contains(sgt.getValue()));
+    @Override
+    public void assignIseContext(final @Nullable IseContext iseContext) {
+        this.iseContext = Optional.ofNullable(iseContext);
     }
 
     @Override
-    public void assignIseSourceConfig(final @Nullable IseSourceConfig iseSourceConfig) {
-        this.iseSourceConfig = Optional.ofNullable(iseSourceConfig);
+    public void setIseSgtHarvester(final GbpIseSgtHarvester iseSgtHarvester) {
+        this.iseSgtHarvester = iseSgtHarvester;
     }
 }
index 93f6ddb8dc82db691546b4d8b573d086139c55d9..e623502c035f9f0d77140b41cac6fdda517b2544 100644 (file)
@@ -75,6 +75,7 @@ public class GbpIseAdapterProvider implements AutoCloseable, BindingAwareProvide
         final GbpIseSgtHarvester gbpIseSgtHarvester = new GbpIseSgtHarvesterImpl(epgGenerator, templateGenerator);
         final GbpIseConfigListenerImpl gbpIseConfigListener = new GbpIseConfigListenerImpl(
                 dataBroker, gbpIseSgtHarvester, templateProviderFacade);
+        templateProviderFacade.setIseSgtHarvester(gbpIseSgtHarvester);
 
         // build data-tree path
         final DataTreeIdentifier<IseSourceConfig> dataTreePath = new DataTreeIdentifier<>(
index bcb2c7c9a0fb955fe6cddca9fe8775d98d5ec2b3..031f9bfd6d86e916ca3bb843c22b27f6c71310d9 100644 (file)
@@ -16,6 +16,7 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Date;
+import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -30,9 +31,9 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DateAndTime;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.integration.sxp.ise.adapter.model.rev160630.GbpSxpIseAdapter;
-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.IseHarvestStatus;
 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.IseHarvestStatusBuilder;
+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.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -73,15 +74,16 @@ public class GbpIseConfigListenerImpl implements GbpIseConfigListener {
         for (DataTreeModification<IseSourceConfig> modification : collection) {
             final IseSourceConfig iseSourceConfig = modification.getRootNode().getDataAfter();
             //TODO: separate template provider from harvesting
-            templateProviderFacade.assignIseSourceConfig(iseSourceConfig);
+            final IseContext iseContext = new IseContext(iseSourceConfig);
+            templateProviderFacade.assignIseContext(iseContext);
             if (iseSourceConfig != null) {
                 pool.submit(() -> {
-                    final ListenableFuture<Integer> harvestResult = gbpIseSgtHarvester.harvest(iseSourceConfig);
-                    Futures.addCallback(harvestResult, new FutureCallback<Integer>() {
+                    final ListenableFuture<Collection<SgtInfo>> harvestResult = gbpIseSgtHarvester.harvestAll(iseContext);
+                    Futures.addCallback(harvestResult, new FutureCallback<Collection<SgtInfo>>() {
                         @Override
-                        public void onSuccess(@Nullable final Integer result) {
+                        public void onSuccess(@Nullable final Collection<SgtInfo> result) {
                             LOG.debug("ise harvest finished, outcome: {}", result);
-                            storeOutcome(true, result.intValue(), null);
+                            storeOutcome(true, Optional.ofNullable(result).map(Collection::size).orElse(0), null);
                         }
 
                         @Override
index a1db1b89ded5a87d92dd9309d07c623612405e21..9cecd622e7a7b1795038b3374b39558b06b55be3 100644 (file)
@@ -9,8 +9,8 @@
 package org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl;
 
 import com.google.common.util.concurrent.ListenableFuture;
+import java.util.Collection;
 import javax.annotation.Nonnull;
-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;
 
 /**
  * Purpose: read sgts and naming from ISE via rest-API and have apropriate templates generated and stored
@@ -18,8 +18,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controll
 public interface GbpIseSgtHarvester {
 
     /**
-     * @param configuration user given
-     * @return amount of successfully written items
+     * @param iseContext user given ise info
+     * @return retrieved and stored sgts
      */
-    ListenableFuture<Integer> harvest(@Nonnull IseSourceConfig configuration);
+    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 4b610ca9d1feac21df0949ef3cb9b5bec9f29a15..74dee902638adf5da3301baf2845b69acf389bde 100644 (file)
@@ -17,6 +17,7 @@ import com.sun.jersey.api.client.Client;
 import com.sun.jersey.api.client.WebResource;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.Callable;
@@ -59,9 +60,10 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
     }
 
     @Override
-    public ListenableFuture<Integer> harvest(@Nonnull final IseSourceConfig configuration) {
-        final ConnectionConfig connectionConfig = configuration.getConnectionConfig();
-        ListenableFuture<Integer> result;
+    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());
@@ -78,16 +80,16 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
                     @Override
                     public ListenableFuture<Void> apply(final Void input) throws Exception {
                         LOG.debug("entering stg-info processor {}", processor.getClass().getSimpleName());
-                        return processor.processSgtInfo(configuration.getTenant(), sgtInfos);
+                        return processor.processSgtInfo(iseSourceConfig.getTenant(), sgtInfos);
                     }
                 });
             }
-            result = Futures.transform(processingResult, new Function<Void, Integer>() {
+            result = Futures.transform(processingResult, new Function<Void, Collection<SgtInfo>>() {
                 @Nullable
                 @Override
-                public Integer apply(@Nullable final Void input) {
+                public Collection<SgtInfo> apply(@Nullable final Void input) {
                     // always success, otherwise there will be TransactionCommitFailedException thrown
-                    return sgtInfos.size();
+                    return sgtInfos;
                 }
             });
         } catch (Exception e) {
@@ -136,7 +138,7 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
             // stop pool
             pool.shutdown();
             final boolean terminated = pool.awaitTermination(1, TimeUnit.MINUTES);
-            if (!terminated) {
+            if (! terminated) {
                 LOG.debug("NOT all sgt-detail queries succeeded - timed out");
                 pool.shutdownNow();
             }
@@ -153,7 +155,7 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
 
     private SgtInfo gainSgtInfoSafely(final Future<SgtInfo> response) {
         SgtInfo result = null;
-        if (response.isDone() && !response.isCancelled()) {
+        if (response.isDone() && ! response.isCancelled()) {
             try {
                 result = response.get();
             } catch (Exception e) {
@@ -176,12 +178,18 @@ public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester {
         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);
         LOG.debug("sgt value [{}]: {} -> {}", idx, sgtValue, sgtName);
 
         // store replies into list of SgtInfo
         final Sgt sgt = new Sgt(Integer.parseInt(sgtValue.getNodeValue(), 10));
-        return new SgtInfo(sgt, sgtName.getNodeValue());
+        return new SgtInfo(sgt, sgtName.getNodeValue(), sgtUuid.getNodeValue());
     }
 
+    @Override
+    public ListenableFuture<Collection<SgtInfo>> update(@Nonnull final IseContext iseContext) {
+        //TODO: stub
+        return null;
+    }
 }
diff --git a/sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/IseContext.java b/sxp-integration/sxp-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/sxp_ise_adapter/impl/IseContext.java
new file mode 100644 (file)
index 0000000..dcb3393
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.util.HashMap;
+import java.util.Map;
+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;
+
+/**
+ * Purpose: keeper of {@link IseSourceConfig}, UUID-to-SGT map
+ * <br>
+ * Unique identifier is tenant-id (expect 1 tenant = 1 ise-source)
+ */
+public class IseContext {
+
+    private final IseSourceConfig iseSourceConfig;
+    private final Map<String, Integer> uuidToSgtMap;
+
+    /**
+     * default ctor
+     * @param iseSourceConfig ise provider coordinates
+     */
+    public IseContext(final IseSourceConfig iseSourceConfig) {
+        this.iseSourceConfig = iseSourceConfig;
+        this.uuidToSgtMap = new HashMap<>();
+    }
+
+    /**
+     * @return ise coordinates
+     */
+    public IseSourceConfig getIseSourceConfig() {
+        return iseSourceConfig;
+    }
+
+    /**
+     * @return known UUID-to-SGT relations
+     */
+    public Map<String, Integer> getUuidToSgtMap() {
+        return uuidToSgtMap;
+    }
+}
index 5315a9449d6c2093364527803b1cdd832c639d81..173a593403ac55fcbe42ba9bddb74d7e6ef881be 100644 (file)
@@ -19,14 +19,17 @@ public class SgtInfo {
 
     private final Sgt sgt;
     private final String name;
+    private final String uuid;
 
     /**
      * @param sgt  value to hold
      * @param name value to hold
+     * @param uuid
      */
-    public SgtInfo(@Nonnull final Sgt sgt, @Nullable final String name) {
+    public SgtInfo(@Nonnull final Sgt sgt, @Nullable final String name, final String uuid) {
         this.sgt = sgt;
         this.name = name;
+        this.uuid = uuid;
     }
 
     /**
index 13e4f5263ee2c2c399d512628ba514ae58965f91..3861765f25ba0705bc8252d1cec79530e26fd9b3 100644 (file)
@@ -26,6 +26,7 @@ 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 IseReplyUtil() {
index f31b21cfa72b3e56f54d96597f8893458efec9eb..126ee61eb89a768b40a5210459747ad360822180 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl;
 import static org.powermock.api.support.membermodification.MemberMatcher.method;
 import static org.powermock.api.support.membermodification.MemberModifier.stub;
 
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.sun.jersey.api.client.Client;
 import com.sun.jersey.api.client.WebResource;
 import java.util.Collections;
@@ -53,6 +55,7 @@ public class EPPolicyTemplateProviderIseImplTest {
     private static final Sgt SGT_LOW = new Sgt(1);
     private static final Sgt SGT_HI = new Sgt(100);
     private static final TenantId TENANT_ID = new TenantId("tenant-01");
+    private static final SgtInfo SGT_INFO = new SgtInfo(SGT, "ultimate_group", "uuidOf42");
 
     @Mock
     private XPath xpathWalker;
@@ -60,18 +63,25 @@ public class EPPolicyTemplateProviderIseImplTest {
     private Client iseClient;
     @Mock
     private WebResource.Builder wrBuilder;
+    @Mock
+    private GbpIseSgtHarvester iseSgtHarvester;
+    @Mock
+    private IseContext iseContext;
 
     private EPPolicyTemplateProviderIseImpl templateProvider;
 
     @Before
     public void setUp() throws Exception {
         templateProvider = new EPPolicyTemplateProviderIseImpl();
+        templateProvider.setIseSgtHarvester(iseSgtHarvester);
     }
 
     @Test
     public void testProvideTemplate_noConfig() throws Exception {
-        final Optional<EndpointPolicyTemplateBySgt> endpointPolicyTemplateBySgt = templateProvider.provideTemplate(SGT);
-        Assert.assertFalse(endpointPolicyTemplateBySgt.isPresent());
+        final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> endpointPolicyTemplateBySgt =
+                templateProvider.provideTemplate(SGT);
+        Assert.assertTrue(endpointPolicyTemplateBySgt.isDone());
+        Assert.assertFalse(endpointPolicyTemplateBySgt.get().isPresent());
     }
 
     @Test
@@ -99,18 +109,23 @@ public class EPPolicyTemplateProviderIseImplTest {
         stub(method(RestClientFactory.class, "createRequestBuilder", WebResource.class, List.class, String.class)).toReturn(wrBuilder);
 
 
-        final String epgName = "name-for-sgt42";
+        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),
                 Matchers.<InputSource>any(), Matchers.same(XPathConstants.NODE)))
                 .thenReturn(sgtNameNode);
 
-        templateProvider.assignIseSourceConfig(sourceConfig);
-        final Optional<EndpointPolicyTemplateBySgt> templateWrap = templateProvider.provideTemplate(SGT);
+        Mockito.when(iseContext.getIseSourceConfig()).thenReturn(sourceConfig);
+        Mockito.when(iseSgtHarvester.update(iseContext))
+                .thenReturn(Futures.immediateFuture(Collections.singletonList(SGT_INFO)));
+
+        templateProvider.assignIseContext(iseContext);
+        final ListenableFuture<Optional<EndpointPolicyTemplateBySgt>> templateWrap = templateProvider.provideTemplate(SGT);
 
-        Assert.assertTrue(templateWrap.isPresent());
-        final EndpointPolicyTemplateBySgt template = templateWrap.get();
+        Assert.assertTrue(templateWrap.isDone());
+        Assert.assertTrue(templateWrap.get().isPresent());
+        final EndpointPolicyTemplateBySgt template = templateWrap.get().get();
         Assert.assertEquals(SGT, template.getSgt());
         Assert.assertNull(template.getConditions());
         Assert.assertEquals(TENANT_ID, template.getTenant());
index 1bb6a95ee44feb9e4025f810c8470b44c3a8e76e..a70f5aeb47ef6e6b7f17768d2a363a71bae2a9fc 100644 (file)
@@ -8,11 +8,15 @@
 
 package org.opendaylight.groupbasedpolicy.sxp_ise_adapter.impl;
 
+import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Futures;
 import java.util.Collections;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.InOrder;
 import org.mockito.Matchers;
 import org.mockito.Mock;
@@ -25,6 +29,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 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.IseHarvestStatus;
 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.sxp.database.rev160308.Sgt;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 /**
@@ -33,6 +38,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 @RunWith(MockitoJUnitRunner.class)
 public class GbpIseConfigListenerImplTest {
 
+    private static final SgtInfo SGT_INFO = new SgtInfo(new Sgt(42), "ultimate_group", "uuidOf42");
     @Mock
     private DataBroker dataBroker;
     @Mock
@@ -47,6 +53,8 @@ public class GbpIseConfigListenerImplTest {
     private IseSourceConfig config;
     @Mock
     private EPPolicyTemplateProviderFacade templateProviderFacade;
+    @Captor
+    private ArgumentCaptor<IseContext> iseContextCpt;
 
     private GbpIseConfigListenerImpl listener;
 
@@ -69,7 +77,7 @@ public class GbpIseConfigListenerImplTest {
         Mockito.when(dataModification.getDataAfter()).thenReturn(config);
         Mockito.when(treeModification.getRootNode()).thenReturn(dataModification);
 
-        Mockito.when(harvester.harvest(config)).thenReturn(Futures.immediateFuture(42));
+        Mockito.when(harvester.harvestAll(iseContextCpt.capture())).thenReturn(Futures.immediateFuture(Lists.newArrayList(SGT_INFO)));
 
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
         Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx);
@@ -77,8 +85,9 @@ public class GbpIseConfigListenerImplTest {
         listener.onDataTreeChanged(Collections.singleton(treeModification));
         listener.close();
 
+        Assert.assertSame(config, iseContextCpt.getValue().getIseSourceConfig());
         final InOrder inOrder = Mockito.inOrder(harvester, dataBroker, wTx);
-        inOrder.verify(harvester).harvest(config);
+        inOrder.verify(harvester).harvestAll(Matchers.<IseContext>any());
         inOrder.verify(dataBroker).newWriteOnlyTransaction();
         inOrder.verify(wTx).put(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.<InstanceIdentifier<IseHarvestStatus>>any(),
@@ -93,8 +102,8 @@ public class GbpIseConfigListenerImplTest {
         Mockito.when(dataModification.getDataAfter()).thenReturn(config);
         Mockito.when(treeModification.getRootNode()).thenReturn(dataModification);
 
-        Mockito.when(harvester.harvest(config)).thenReturn(Futures.immediateFailedFuture(
-                new Exception("extremely poor harvest occurred")));
+        Mockito.when(harvester.harvestAll(iseContextCpt.capture())).thenReturn(Futures.immediateFailedFuture(
+                new Exception("extremely poor harvestAll occurred")));
 
         Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null));
         Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx);
@@ -102,8 +111,9 @@ public class GbpIseConfigListenerImplTest {
         listener.onDataTreeChanged(Collections.singleton(treeModification));
         listener.close();
 
+        Assert.assertSame(config, iseContextCpt.getValue().getIseSourceConfig());
         final InOrder inOrder = Mockito.inOrder(harvester, dataBroker, wTx);
-        inOrder.verify(harvester).harvest(config);
+        inOrder.verify(harvester).harvestAll(Matchers.<IseContext>any());
         inOrder.verify(dataBroker).newWriteOnlyTransaction();
         inOrder.verify(wTx).put(Matchers.eq(LogicalDatastoreType.OPERATIONAL),
                 Matchers.<InstanceIdentifier<IseHarvestStatus>>any(),
index fc593688582db8cb0b062eb511015502028f8b03..8c3c365a5172dbea8a9cdb44c1327d191a436edd 100644 (file)
@@ -20,6 +20,7 @@ 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;
 import java.util.concurrent.TimeUnit;
@@ -69,6 +70,7 @@ public class GbpIseSgtHarvesterImplTest {
     private ClientResponse response;
 
     private IseSourceConfig config;
+    private IseContext iseContext;
 
     private GbpIseSgtHarvesterImpl harvester;
 
@@ -106,6 +108,7 @@ public class GbpIseSgtHarvesterImplTest {
                         .build())
                 .build();
 
+        iseContext = new IseContext(config);
         harvester = new GbpIseSgtHarvesterImpl(processor);
     }
 
@@ -121,7 +124,7 @@ public class GbpIseSgtHarvesterImplTest {
         Mockito.when(processor.processSgtInfo(Matchers.eq(TENANT_ID), Matchers.<List<SgtInfo>>any())).thenReturn(
                 Futures.immediateCheckedFuture(null));
 
-        final ListenableFuture<Integer> harvestResult = harvester.harvest(config);
+        final ListenableFuture<Collection<SgtInfo>> harvestResult = harvester.harvestAll(iseContext);
 
         final InOrder inOrder = Mockito.inOrder(client, webResource, builder);
         inOrder.verify(client).resource(ISE_REST_URL.getValue());
@@ -137,7 +140,7 @@ public class GbpIseSgtHarvesterImplTest {
         inOrder.verify(builder).get(ClientResponse.class);
         inOrder.verifyNoMoreInteractions();
 
-        final Integer count = harvestResult.get(2, TimeUnit.SECONDS);
-        Assert.assertEquals(1, count.intValue());
+        final Collection<SgtInfo> count = harvestResult.get(2, TimeUnit.SECONDS);
+        Assert.assertEquals(1, count.size());
     }
 }
\ No newline at end of file
index ec07e08fb59353c96f3ff11da03d30f778513fe5..e0a04a7ffc7919f8602eec14ef9b3f9f8fa7ad0a 100644 (file)
@@ -42,8 +42,10 @@ public class SgtToEPTemplateGeneratorImplTest {
 
     public static final TenantId TENANT_ID = new TenantId("tenant-unit-1");
     public static final Sgt SGT_1 = new Sgt(1);
+    public static final String SGT_1_UUID = "uuid-1";
     public static final String EPG_NAME_1 = "epg-unit-1";
     public static final Sgt SGT_2 = new Sgt(2);
+    public static final String SGT_2_UUID = "uuid-2";
     public static final String EPG_NAME_2 = "epg-unit-2";
 
     @Mock
@@ -62,8 +64,8 @@ public class SgtToEPTemplateGeneratorImplTest {
 
     @Test
     public void testProcessSgtInfo() throws Exception {
-        final SgtInfo sgtInfo1 = new SgtInfo(SGT_1, EPG_NAME_1);
-        final SgtInfo sgtInfo2 = new SgtInfo(SGT_2, EPG_NAME_2);
+        final SgtInfo sgtInfo1 = new SgtInfo(SGT_1, EPG_NAME_1, SGT_1_UUID);
+        final SgtInfo sgtInfo2 = new SgtInfo(SGT_2, EPG_NAME_2, SGT_2_UUID);
 
         final CheckedFuture<Void, TransactionCommitFailedException> outcome =
                 generator.processSgtInfo(TENANT_ID, Lists.newArrayList(sgtInfo1, sgtInfo2));
index b2463cdcf00c98ca6dbd520a8b6595010aa08087..869d968379b13169450e89acab277e6e938880f8 100644 (file)
@@ -41,8 +41,10 @@ public class SgtToEpgGeneratorImplTest {
 
     public static final TenantId TENANT_ID = new TenantId("tenant-unit-1");
     public static final Sgt SGT_1 = new Sgt(1);
+    public static final String SGT_1_UUID = "uuid-1";
     public static final String EPG_NAME_1 = "epg-unit-1";
     public static final Sgt SGT_2 = new Sgt(2);
+    public static final String SGT_2_UUID = "uuid-2";
     public static final String EPG_NAME_2 = "epg-unit-2";
 
     @Mock
@@ -61,8 +63,8 @@ public class SgtToEpgGeneratorImplTest {
 
     @Test
     public void testProcessSgtInfo() throws Exception {
-        final SgtInfo sgtInfo1 = new SgtInfo(SGT_1, EPG_NAME_1);
-        final SgtInfo sgtInfo2 = new SgtInfo(SGT_2, EPG_NAME_2);
+        final SgtInfo sgtInfo1 = new SgtInfo(SGT_1, EPG_NAME_1, SGT_1_UUID);
+        final SgtInfo sgtInfo2 = new SgtInfo(SGT_2, EPG_NAME_2, SGT_2_UUID);
 
         final CheckedFuture<Void, TransactionCommitFailedException> outcome =
                 generator.processSgtInfo(TENANT_ID, Lists.newArrayList(sgtInfo1, sgtInfo2));