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;
* @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);
}
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;
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>>() {
.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);
@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);
.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);
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);
}
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}
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,
.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;
}
}
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<>(
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;
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;
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
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
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);
}
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;
}
@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());
@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) {
// 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();
}
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) {
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;
+ }
}
--- /dev/null
+/*
+ * 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;
+ }
+}
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;
}
/**
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() {
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;
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;
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
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());
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;
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;
/**
@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
private IseSourceConfig config;
@Mock
private EPPolicyTemplateProviderFacade templateProviderFacade;
+ @Captor
+ private ArgumentCaptor<IseContext> iseContextCpt;
private GbpIseConfigListenerImpl listener;
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);
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(),
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);
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(),
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;
private ClientResponse response;
private IseSourceConfig config;
+ private IseContext iseContext;
private GbpIseSgtHarvesterImpl harvester;
.build())
.build();
+ iseContext = new IseContext(config);
harvester = new GbpIseSgtHarvesterImpl(processor);
}
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());
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
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
@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));
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
@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));