From: Michal Rehak Date: Thu, 30 Jun 2016 16:59:17 +0000 (+0200) Subject: gbp-ise-adapter proposal X-Git-Tag: release/boron~62 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=a28f9f94cdf628e174f3aa8f500e3de2ac23aa8a;p=groupbasedpolicy.git gbp-ise-adapter proposal - initial structure - config - models - api+impl partial stubs - generating epgs - generating ep-policy-templates - storing outcome status - added unit tests - fixed javadoc/copyright issues - squashed interfaces from api to impl Change-Id: I2bd09e56c5afb26616b0febb5bd74c86eb4bd447 Signed-off-by: Michal Rehak --- diff --git a/artifacts/pom.xml b/artifacts/pom.xml index e6d732605..df5c6732d 100755 --- a/artifacts/pom.xml +++ b/artifacts/pom.xml @@ -101,6 +101,11 @@ sxp-mapper ${project.version} + + ${project.groupId} + groupbasedpolicy-ise-adapter + ${project.version} + @@ -208,6 +213,13 @@ xml config + + ${project.groupId} + groupbasedpolicy-ise-adapter + ${project.version} + xml + config + diff --git a/features/pom.xml b/features/pom.xml index 41364081f..02e33de35 100755 --- a/features/pom.xml +++ b/features/pom.xml @@ -311,6 +311,10 @@ org.opendaylight.groupbasedpolicy ios-xe-renderer + + org.opendaylight.groupbasedpolicy + groupbasedpolicy-ise-adapter + @@ -397,5 +401,11 @@ xml config + + org.opendaylight.groupbasedpolicy + groupbasedpolicy-ise-adapter + xml + config + diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml index cea8f8dbc..0d87284cd 100755 --- a/features/src/main/features/features.xml +++ b/features/src/main/features/features.xml @@ -219,4 +219,17 @@ mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}/xml/config mvn:org.opendaylight.groupbasedpolicy/ios-xe-renderer/{{VERSION}}/xml/config + + + + odl-groupbasedpolicy-sxp-mapper + odl-sxp-core + mvn:commons-net/commons-net/{{VERSION}} + mvn:com.sun.jersey/jersey-client/{{VERSION}} + mvn:com.sun.jersey/jersey-core/{{VERSION}} + mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-ise-adapter/{{VERSION}} + mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-ise-adapter/{{VERSION}}/xml/config + diff --git a/groupbasedpolicy-ise-adapter/pom.xml b/groupbasedpolicy-ise-adapter/pom.xml new file mode 100755 index 000000000..4300f466f --- /dev/null +++ b/groupbasedpolicy-ise-adapter/pom.xml @@ -0,0 +1,117 @@ + + + + 4.0.0 + + org.opendaylight.controller + config-parent + 0.5.0-SNAPSHOT + + + + org.opendaylight.groupbasedpolicy + groupbasedpolicy-ise-adapter + 0.4.0-SNAPSHOT + bundle + groupbasedpolicy-ise-adapter + + + 1.3.0-SNAPSHOT + + + + + + org.opendaylight.groupbasedpolicy + groupbasedpolicy-artifacts + ${project.version} + import + pom + + + org.opendaylight.sxp + sxp-api + ${sxp.version} + + + + + + + + org.opendaylight.groupbasedpolicy + sxp-mapper + + + org.opendaylight.sxp + sxp-api + + + + org.opendaylight.mdsal.model + ietf-inet-types + + + org.opendaylight.mdsal.model + ietf-yang-types + + + + + commons-net + commons-net + + + com.sun.jersey + jersey-client + + + + + junit + junit + test + + + org.mockito + mockito-all + test + + + org.slf4j + slf4j-log4j12 + test + + + org.powermock + powermock-module-junit4 + test + + + org.powermock + powermock-api-mockito + test + + + org.opendaylight.controller + sal-binding-broker-impl + test-jar + test + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + diff --git a/groupbasedpolicy-ise-adapter/src/main/config/default-config.xml b/groupbasedpolicy-ise-adapter/src/main/config/default-config.xml new file mode 100755 index 000000000..2f71a2c51 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/config/default-config.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + gbp-ise-adapter:gbp-ise-adapter-impl + + gbp-ise-adapter + + + binding:binding-async-data-broker + binding-data-broker + + + binding:binding-broker-osgi-registry + binding-osgi-broker + + + + + + + + urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:gbp-ise-adapter?module=gbp-ise-adapter-cfg&revision=2016-06-30 + urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:gbp-ise-adapter:model?module=gbp-ise-adapter-model&revision=2016-06-30 + + + diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/gbp_ise_adapter/GpbIseAdapterProviderModule.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/gbp_ise_adapter/GpbIseAdapterProviderModule.java new file mode 100644 index 000000000..415f9e908 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/gbp_ise_adapter/GpbIseAdapterProviderModule.java @@ -0,0 +1,35 @@ +/* + * 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.controller.config.yang.config.groupbasedpolicy.gbp_ise_adapter; + +import org.opendaylight.groupbasedpolicy.gbp_ise_adapter.impl.GbpIseAdapterProvider; + +/** +* gbp-ise-adapter impl module +*/ +public class GpbIseAdapterProviderModule extends org.opendaylight.controller.config.yang.config.groupbasedpolicy.gbp_ise_adapter.AbstractGpbIseAdapterProviderModule { + public GpbIseAdapterProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public GpbIseAdapterProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.groupbasedpolicy.gbp_ise_adapter.GpbIseAdapterProviderModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + return new GbpIseAdapterProvider(getDataBrokerDependency(), getBrokerDependency()); + } + +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/gbp_ise_adapter/GpbIseAdapterProviderModuleFactory.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/gbp_ise_adapter/GpbIseAdapterProviderModuleFactory.java new file mode 100644 index 000000000..4c154475c --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/controller/config/yang/config/groupbasedpolicy/gbp_ise_adapter/GpbIseAdapterProviderModuleFactory.java @@ -0,0 +1,21 @@ +/* + * 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 + */ + +/* +* Generated file +* +* Generated from: yang module name: gbp-ise-adapter-cfg yang module local name: gbp-ise-adapter-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Thu Jun 30 17:44:55 CEST 2016 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.controller.config.yang.config.groupbasedpolicy.gbp_ise_adapter; +public class GpbIseAdapterProviderModuleFactory extends org.opendaylight.controller.config.yang.config.groupbasedpolicy.gbp_ise_adapter.AbstractGpbIseAdapterProviderModuleFactory { + +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseAdapterProvider.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseAdapterProvider.java new file mode 100644 index 000000000..b29509726 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseAdapterProvider.java @@ -0,0 +1,70 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.base.Preconditions; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.GbpIseAdapter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: main provider of gbp-ise adapter (for reading sgts and generating EndpointPolicyTemplates) + */ +public class GbpIseAdapterProvider implements AutoCloseable, BindingAwareProvider { + + private static final Logger LOG = LoggerFactory.getLogger(GbpIseAdapterProvider.class); + + private final DataBroker dataBroker; + private ListenerRegistration> registration; + + public GbpIseAdapterProvider(final DataBroker dataBroker, final BindingAwareBroker brokerDependency) { + this.dataBroker = Preconditions.checkNotNull(dataBroker, "provided dataBroker must not be null"); + brokerDependency.registerProvider(this); + } + + @Override + public void close() throws Exception { + if (registration != null) { + LOG.info("closing GbpIseAdapterProvider"); + registration.close(); + registration = null; + } + } + + @Override + public void onSessionInitiated(final BindingAwareBroker.ProviderContext providerContext) { + LOG.info("Starting GbpIseAdapterProvider .."); + + // setup harvesting and processing pipeline + final SgtInfoProcessor epgGenerator = new SgtToEpgGeneratorImpl(dataBroker); + final SgtInfoProcessor templateGenerator = new SgtToEPTemplateGeneratorImpl(dataBroker); + final GbpIseSgtHarvester gbpIseSgtHarvester = new GbpIseSgtHarvesterImpl(epgGenerator, templateGenerator); + final GbpIseConfigListenerImpl gbpIseConfigListener = new GbpIseConfigListenerImpl(dataBroker, gbpIseSgtHarvester); + + // build data-tree path + final DataTreeIdentifier dataTreePath = new DataTreeIdentifier<>( + LogicalDatastoreType.CONFIGURATION, + InstanceIdentifier.create(GbpIseAdapter.class).child(IseHarvestConfig.class)); + + // register config listener + registration = dataBroker.registerDataTreeChangeListener(dataTreePath, + gbpIseConfigListener); + + LOG.info("Started"); + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListener.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListener.java new file mode 100644 index 000000000..399ca5f9b --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListener.java @@ -0,0 +1,19 @@ +/* + * 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.gbp_ise_adapter.impl; + +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; + +/** + * Purpose: dtcl for {@link IseHarvestConfig} + */ +public interface GbpIseConfigListener extends DataTreeChangeListener, AutoCloseable { + // nobody +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListenerImpl.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListenerImpl.java new file mode 100644 index 000000000..e613ca9be --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListenerImpl.java @@ -0,0 +1,128 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +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.rev100924.DateAndTime; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.GbpIseAdapter; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestStatusBuilder; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: listen for harvest configuration and trigger harvesting + */ +public class GbpIseConfigListenerImpl implements GbpIseConfigListener { + + private static final Logger LOG = LoggerFactory.getLogger(GbpIseConfigListenerImpl.class); + + private static final String DATE_AND_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; + + private final DataBroker dataBroker; + private final GbpIseSgtHarvester gbpIseSgtHarvester; + private final ThreadPoolExecutor pool; + + public GbpIseConfigListenerImpl(@Nonnull final DataBroker dataBroker, @Nonnull final GbpIseSgtHarvester gbpIseSgtHarvester) { + this.dataBroker = dataBroker; + this.gbpIseSgtHarvester = gbpIseSgtHarvester; + pool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(10), + new ThreadFactoryBuilder().setNameFormat("ise-sgt-harverster-%d").build()) { + @Override + protected void afterExecute(final Runnable r, final Throwable t) { + super.afterExecute(r, t); + if (t != null) { + LOG.warn("ise harvest task failed", t); + } + } + }; + } + + @Override + public void onDataTreeChanged(@Nonnull final Collection> collection) { + for (DataTreeModification modification : collection) { + final IseHarvestConfig iseHarvestConfig = modification.getRootNode().getDataAfter(); + if (iseHarvestConfig != null) { + pool.submit(() -> { + final ListenableFuture harvestResult = gbpIseSgtHarvester.harvest(iseHarvestConfig); + Futures.addCallback(harvestResult, new FutureCallback() { + @Override + public void onSuccess(@Nullable final Integer result) { + LOG.debug("ise harvest finished, outcome: {}", result); + storeOutcome(true, result.intValue(), null); + } + + @Override + public void onFailure(final Throwable t) { + LOG.debug("ise harvest failed", t); + storeOutcome(false, 0, t.getMessage()); + } + }); + + try { + harvestResult.get(30, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOG.debug("failed to finish ise-sgt-harvest task properly on time", e); + } + }); + } + } + } + + private CheckedFuture storeOutcome(final boolean succeeded, final int counter, final String reason) { + final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction(); + final InstanceIdentifier harvestStatusPath = InstanceIdentifier.create(GbpIseAdapter.class) + .child(IseHarvestStatus.class); + final IseHarvestStatus harvestStatus = new IseHarvestStatusBuilder() + .setReason(reason) + .setSuccess(succeeded) + .setTemplatesWritten(counter) + .setTimestamp(createDateTime(new Date())) + .build(); + wTx.put(LogicalDatastoreType.OPERATIONAL, harvestStatusPath, harvestStatus, true); + return wTx.submit(); + } + + private static DateAndTime createDateTime(Date when) { + final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_AND_TIME_FORMAT); + return new DateAndTime(simpleDateFormat.format(when)); + } + + @Override + public void close() throws Exception { + if (!pool.isTerminated()) { + pool.shutdown(); + final boolean terminated = pool.awaitTermination(10, TimeUnit.SECONDS); + if (! terminated) { + pool.shutdownNow(); + } + } + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvester.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvester.java new file mode 100644 index 000000000..d551e7ae2 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvester.java @@ -0,0 +1,25 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.util.concurrent.ListenableFuture; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; + +/** + * 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 + */ + ListenableFuture harvest(@Nonnull IseHarvestConfig configuration); +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvesterImpl.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvesterImpl.java new file mode 100644 index 000000000..bff6d7ed2 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvesterImpl.java @@ -0,0 +1,194 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.base.Function; +import com.google.common.util.concurrent.AsyncFunction; +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.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import java.io.StringReader; +import java.net.URI; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +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.opendaylight.groupbasedpolicy.gbp_ise_adapter.impl.util.RestClientFactory; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.ise.harvest.config.ConnectionConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.ise.harvest.config.connection.config.Header; +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; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +/** + * Purpose: harvest sgt + names available via ise-rest-api + */ +public class GbpIseSgtHarvesterImpl implements GbpIseSgtHarvester { + + private static final Logger LOG = LoggerFactory.getLogger(GbpIseSgtHarvesterImpl.class); + + public static final String PATH_ERS_CONFIG_SGT = "/ers/config/sgt"; + 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_VALUE = "./value/text()"; + + private final SgtInfoProcessor[] sgtInfoProcessors; + + /** + * @param sgtInfoProcessors generator delegate + */ + public GbpIseSgtHarvesterImpl(final SgtInfoProcessor... sgtInfoProcessors) { + this.sgtInfoProcessors = sgtInfoProcessors; + } + + @Override + public ListenableFuture harvest(@Nonnull final IseHarvestConfig configuration) { + final ConnectionConfig connectionConfig = configuration.getConnectionConfig(); + ListenableFuture result; + try { + final Client iseClient = RestClientFactory.createIseClient(connectionConfig); + final WebResource baseWebResource = iseClient.resource(connectionConfig.getIseRestUrl().getValue()); + + final WebResource.Builder requestBuilder = createRequestBuilder(baseWebResource, + connectionConfig.getHeader(), PATH_ERS_CONFIG_SGT); + final String rawSgtSummary = deliverResponse(requestBuilder); + + final List sgtInfos = harvestDetails(rawSgtSummary, baseWebResource, connectionConfig.getHeader()); + + ListenableFuture processingResult = Futures.immediateCheckedFuture(null); + for (SgtInfoProcessor processor : sgtInfoProcessors) { + processingResult = Futures.transform(processingResult, new AsyncFunction() { + @Override + public ListenableFuture apply(final Void input) throws Exception { + LOG.debug("entering stg-info processor {}", processor.getClass().getSimpleName()); + return processor.processSgtInfo(configuration.getTenant(), sgtInfos); + } + }); + } + result = Futures.transform(processingResult, new Function() { + @Nullable + @Override + public Integer apply(@Nullable final Void input) { + // always success, otherwise there will be TransactionCommitFailedException thrown + return sgtInfos.size(); + } + }); + } catch (Exception e) { + LOG.debug("failed to harvest ise", e); + result = Futures.immediateFailedFuture(e); + } + + return result; + } + + private static String deliverResponse(final WebResource.Builder requestBuilder) { + return requestBuilder.get(ClientResponse.class).getEntity(String.class); + } + + private static WebResource.Builder createRequestBuilder(final WebResource resource, final List
headers, + final String path) { + final WebResource webResource = resource.path(path); + final WebResource.Builder requestBuilder = webResource.getRequestBuilder(); + headers.stream().forEach( + (header) -> requestBuilder.header(header.getName(), header.getValue())); + return requestBuilder; + } + + private List harvestDetails(final String rawSgtSummary, final WebResource baseWebResource, final List
headers) { + LOG.trace("rawSgtSummary: {}", rawSgtSummary); + final List sgtInfos = new ArrayList<>(); + + // parse sgtSummary + final XPath xpath = setupXpath(); + + InputSource inputSource = new InputSource(new StringReader(rawSgtSummary)); + try { + final NodeList sgtLinkNodes = (NodeList) xpath.evaluate(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); + + // query all sgt entries (serial-vise) + final URI hrefToSgtDetailUri = URI.create(sgtLinkHrefValue); + final WebResource.Builder requestBuilder = createRequestBuilder(baseWebResource, headers, hrefToSgtDetailUri.getPath()); + final String rawSgtDetail = deliverResponse(requestBuilder); + LOG.trace("rawSgtDetail: {}", rawSgtDetail); + + final Node sgtNode = (Node) xpath.evaluate(EXPRESSION_SGT_DETAIL, new InputSource(new StringReader(rawSgtDetail)), + XPathConstants.NODE); + final Node sgtName = (Node) xpath.evaluate(EXPRESSION_SGT_NAME_ATTR, sgtNode, XPathConstants.NODE); + final Node sgtValue = (Node) xpath.evaluate(EXPRESSION_SGT_VALUE, sgtNode, XPathConstants.NODE); + LOG.debug("sgt value [{}]: {} -> {}", i, sgtValue, sgtName); + + // store replies into list of SgtInfo + final Sgt sgt = new Sgt(Integer.parseInt(sgtValue.getNodeValue(), 10)); + final SgtInfo sgtInfo = new SgtInfo(sgt, sgtName.getNodeValue()); + sgtInfos.add(sgtInfo); + } + } catch (XPathExpressionException e) { + LOG.warn("failed to parse all-sgt response", e); + } + + return sgtInfos; + } + + /** + * @return initiated xpath with ise namespace context injected + */ + private static XPath setupXpath() { + final NamespaceContext nsContext = new NamespaceContext() { + public String getNamespaceURI(String prefix) { + final String outcome; + if (prefix == null) { + throw new NullPointerException("Null prefix"); + } + + if ("ns5".equals(prefix)) { + outcome = "ers.ise.cisco.com"; + } else if ("ns3".equals(prefix)) { + outcome = "v2.ers.ise.cisco.com"; + } else if ("ns4".equals(prefix)) { + outcome = "trustsec.ers.ise.cisco.com"; + } else { + outcome = XMLConstants.NULL_NS_URI; + } + return outcome; + } + + // This method isn't necessary for XPath processing. + public String getPrefix(String uri) { + throw new UnsupportedOperationException(); + } + + // This method isn't necessary for XPath processing either. + public Iterator getPrefixes(String uri) { + throw new UnsupportedOperationException(); + } + }; + + XPath xpath = XPathFactory.newInstance().newXPath(); + xpath.setNamespaceContext(nsContext); + return xpath; + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtInfo.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtInfo.java new file mode 100644 index 000000000..015e282e9 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtInfo.java @@ -0,0 +1,45 @@ +/* + * 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.gbp_ise_adapter.impl; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; + +/** + * Purpose: simple holder for {@link Sgt} and name + */ +public class SgtInfo { + + private final Sgt sgt; + private final String name; + + /** + * @param sgt value to hold + * @param name value to hold + */ + public SgtInfo(@Nonnull final Sgt sgt, @Nullable final String name) { + this.sgt = sgt; + this.name = name; + } + + /** + * @return sgt + */ + public Sgt getSgt() { + return sgt; + } + + /** + * @return name associated to sgt + */ + public String getName() { + return name; + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtInfoProcessor.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtInfoProcessor.java new file mode 100644 index 000000000..e28151525 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtInfoProcessor.java @@ -0,0 +1,27 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.util.concurrent.CheckedFuture; +import java.util.List; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId; + +/** + * Purpose: process given sgt+name + */ +public interface SgtInfoProcessor { + + /** + * @param tenant shared by all processed epgs + * @param sgtInfos list of sgts to process + * @return outcome of dataStore write operation + */ + CheckedFuture processSgtInfo(final TenantId tenant, List sgtInfos); +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEPTemplateGeneratorImpl.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEPTemplateGeneratorImpl.java new file mode 100644 index 000000000..c5521e387 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEPTemplateGeneratorImpl.java @@ -0,0 +1,69 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.util.concurrent.CheckedFuture; +import java.util.Collections; +import java.util.List; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +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.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.mapper.model.rev160302.SxpMapper; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: process given sgt+name - create {@link EndpointPolicyTemplateBySgt} and write it to sxp-mapper templates + */ +public class SgtToEPTemplateGeneratorImpl implements SgtInfoProcessor { + + private static final Logger LOG = LoggerFactory.getLogger(SgtToEPTemplateGeneratorImpl.class); + + private final DataBroker dataBroker; + + public SgtToEPTemplateGeneratorImpl(final DataBroker dataBroker) { + this.dataBroker = dataBroker; + } + + @Override + public CheckedFuture processSgtInfo(final TenantId tenantId, final List sgtInfos) { + final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction(); + + // write endpoint-policy-templates + boolean createParent = true; + for (SgtInfo sgtInfo : sgtInfos) { + final Sgt sgt = sgtInfo.getSgt(); + final String sgtName = sgtInfo.getName(); + LOG.trace("processing sgtInfo: {} - {}", sgt.getValue(), sgtName); + + final EndpointGroupId epgId = new EndpointGroupId(sgtInfo.getName()); + + final InstanceIdentifier epPolicyTemplatePath = InstanceIdentifier + .create(SxpMapper.class) + .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(sgt)); + + final EndpointPolicyTemplateBySgt epPolicyTemplate = new EndpointPolicyTemplateBySgtBuilder() + .setSgt(sgt) + .setEndpointGroups(Collections.singletonList(epgId)) + .setTenant(tenantId) + .build(); + wTx.put(LogicalDatastoreType.CONFIGURATION, epPolicyTemplatePath, epPolicyTemplate, createParent); + createParent = false; + } + return wTx.submit(); + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEpgGeneratorImpl.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEpgGeneratorImpl.java new file mode 100644 index 000000000..36281370f --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEpgGeneratorImpl.java @@ -0,0 +1,64 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.util.concurrent.CheckedFuture; +import java.util.List; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +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.common.rev140421.TenantId; +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.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Purpose: process given sgt+name - create {@link EndpointGroup} and write it to tenants/tenant/policy/endpoint-group + */ +public class SgtToEpgGeneratorImpl implements SgtInfoProcessor { + + private static final Logger LOG = LoggerFactory.getLogger(SgtToEpgGeneratorImpl.class); + + private final DataBroker dataBroker; + + public SgtToEpgGeneratorImpl(final DataBroker dataBroker) { + this.dataBroker = dataBroker; + } + + @Override + public CheckedFuture processSgtInfo(final TenantId tenantId, final List sgtInfos) { + final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction(); + + // create and write endpointgroups + boolean createParent = true; + for (SgtInfo sgtInfo : sgtInfos) { + final Integer sgtValue = sgtInfo.getSgt().getValue(); + final String sgtName = sgtInfo.getName(); + LOG.trace("processing sgtInfo: {} - {}", sgtValue, sgtName); + + final EndpointGroupId epgId = new EndpointGroupId(sgtName); + final InstanceIdentifier epgPath = IidFactory.endpointGroupIid(tenantId, epgId); + final EndpointGroup epg = new EndpointGroupBuilder() + .setId(epgId) + .setDescription(new Description("imported from ISE for sgt=" + sgtValue)) + .setName(new Name(sgtName.replaceAll(" ", "_") + "--" + sgtValue)) + .build(); + wTx.put(LogicalDatastoreType.CONFIGURATION, epgPath, epg, createParent); + createParent = false; + } + return wTx.submit(); + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/util/RestClientFactory.java b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/util/RestClientFactory.java new file mode 100644 index 000000000..26cc3040e --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/util/RestClientFactory.java @@ -0,0 +1,61 @@ +/* + * 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.gbp_ise_adapter.impl.util; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.client.urlconnection.HTTPSProperties; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import org.apache.commons.net.util.TrustManagerUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.ise.harvest.config.ConnectionConfig; + +/** + * Purpose: setup ise-ready jersey {@link Client} + */ +public class RestClientFactory { + + private RestClientFactory() { + throw new IllegalAccessError("factory class - no instances supported"); + } + + /** + * @param connectionConfig config provided + * @return initiated jersey client - ready to talk to ise + * + * @throws GeneralSecurityException in case when insecure certificate hack fails + */ + public static Client createIseClient(final ConnectionConfig connectionConfig) throws GeneralSecurityException { + final DefaultClientConfig clientConfig = new DefaultClientConfig(); + clientConfig.getProperties() + .put(ClientConfig.PROPERTY_CONNECT_TIMEOUT, connectionConfig.getConnectionTimeout()); + clientConfig.getProperties() + .put(ClientConfig.PROPERTY_READ_TIMEOUT, connectionConfig.getReadTimeout()); + + hackInsecureCertificate(clientConfig); + return Client.create(clientConfig); + } + + private static void hackInsecureCertificate(final ClientConfig clientConfigArg) + throws NoSuchAlgorithmException, KeyManagementException { + final TrustManager[] trustAllCerts = new TrustManager[]{TrustManagerUtils.getAcceptAllTrustManager()}; + + SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, trustAllCerts, null); + + clientConfigArg.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties( + (s, sslSession) -> true, + sslContext + )); + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/yang/gbp-ise-adapter-cfg.yang b/groupbasedpolicy-ise-adapter/src/main/yang/gbp-ise-adapter-cfg.yang new file mode 100644 index 000000000..90548b016 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/yang/gbp-ise-adapter-cfg.yang @@ -0,0 +1,60 @@ +/* + * 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 + */ + +module gbp-ise-adapter-cfg { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:gbp-ise-adapter"; + prefix "gpb-ise-adapter-cfg"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; } + + description + "This module contains the base YANG definitions for + gbp-ise-adapter impl configuration."; + + revision "2016-06-30" { + description + "Initial revision."; + } + + identity gbp-ise-adapter-impl { + description + "gbp-ise-adapter impl module"; + + base "config:module-type"; + config:java-name-prefix GpbIseAdapterProvider; + } + + // Augments the 'configuration' choice node under modules/module. + augment "/config:modules/config:module/config:configuration" { + case gbp-ise-adapter-impl { + when "/config:modules/config:module/config:type = 'gbp-ise-adapter-impl'"; + + //wires in the data-broker service + container data-broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity mdsal:binding-async-data-broker; + } + } + } + + container broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity mdsal:binding-broker-osgi-registry; + } + } + } + + } + } +} diff --git a/groupbasedpolicy-ise-adapter/src/main/yang/gbp-ise-adapter-model.yang b/groupbasedpolicy-ise-adapter/src/main/yang/gbp-ise-adapter-model.yang new file mode 100644 index 000000000..bc59cc5b0 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/main/yang/gbp-ise-adapter-model.yang @@ -0,0 +1,101 @@ +/* + * 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 + */ + +module gbp-ise-adapter-model { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:gbp-ise-adapter:model"; + prefix "gbp-ise-adapter-model"; + + import gbp-common { prefix gbp-common; revision-date 2014-04-21; } + import ietf-inet-types { prefix inet; revision-date 2010-09-24; } + import ietf-yang-types {prefix yang; revision-date "2010-09-24";} + + description + "This module contains the YANG definitions for + gbp-ise-adapter implementation."; + + revision "2016-06-30" { + description + "Initial revision."; + } + + container gbp-ise-adapter { + description "root point for ise connection info and sgt harvest status"; + + container ise-harvest-config { + description "connection + credentials for ise-rest-api connection and target tennant"; + config true; + + leaf tenant { + type gbp-common:tenant-id; + mandatory true; + description + "tenant for all extracted sgt"; + } + + container connection-config { + description "rest connection configuration part"; + + leaf ise-rest-url { + description "base uri to ise-rest-api"; + mandatory true; + type inet:uri; + } + + leaf connection-timeout { + description "connection timeout in milliseconds"; + type uint16; + default 5000; + } + + leaf read-timeout { + description "read from rest timeout in milliseconds"; + type uint16; + default 5000; + } + + list header { + description "request headers in form key+value"; + key name; + + leaf name { + type string; + } + leaf value { + type string; + } + } + } + } + + container ise-harvest-status { + description "result of sgt harvest from ise-rest-api and generating endpoint policy templates"; + config false; + + leaf success { + description "true if all operations succeeded"; + type boolean; + } + + leaf reason { + description "failure detail"; + type string; + } + + leaf templates-written { + description "amount of endpoint templates written"; + type uint16; + } + + leaf timestamp { + description "stamped upon sgts harvested and templates written"; + type yang:date-and-time; + } + } + } +} diff --git a/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseAdapterProviderTest.java b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseAdapterProviderTest.java new file mode 100644 index 000000000..236195dd1 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseAdapterProviderTest.java @@ -0,0 +1,75 @@ +package org.opendaylight.groupbasedpolicy.gbp_ise_adapter.impl; + +import static org.powermock.api.mockito.PowerMockito.verifyNew; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +/** + * Purpose: cover {@link GbpIseAdapterProvider} + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({GbpIseAdapterProvider.class}) +public class GbpIseAdapterProviderTest { + + @Mock + private DataBroker dataBroker; + @Mock + private BindingAwareBroker broker; + @Mock + private BindingAwareBroker.ProviderContext providerContext; + @Mock + private ListenerRegistration registration; + @Mock + private SgtToEpgGeneratorImpl generator1; + @Mock + private SgtToEPTemplateGeneratorImpl generator2; + @Mock + private GbpIseSgtHarvesterImpl harvester; + @Mock + private GbpIseConfigListenerImpl listener; + + private GbpIseAdapterProvider provider; + + @Before + public void setUp() throws Exception { + provider = new GbpIseAdapterProvider(dataBroker, broker); + Mockito.verify(broker).registerProvider(provider); + } + + @Test + public void testOnSessionInitiated() throws Exception { + Mockito.when(dataBroker.registerDataTreeChangeListener( + Matchers.>any(), + Matchers.any())).thenReturn(registration); + + // prepare expectation for objects in onSessionInitiated (powerMock requirement for later checking) + whenNew(SgtToEpgGeneratorImpl.class).withAnyArguments().thenReturn(generator1); + whenNew(SgtToEPTemplateGeneratorImpl.class).withAnyArguments().thenReturn(generator2); + whenNew(GbpIseSgtHarvesterImpl.class).withArguments(generator1, generator2).thenReturn(harvester); + whenNew(GbpIseConfigListenerImpl.class).withAnyArguments().thenReturn(listener); + provider.onSessionInitiated(providerContext); + + // check if all expected object got constructed and wired + verifyNew(SgtToEpgGeneratorImpl.class).withArguments(dataBroker); + verifyNew(SgtToEPTemplateGeneratorImpl.class).withArguments(dataBroker); + verifyNew(GbpIseSgtHarvesterImpl.class).withArguments(generator1, generator2); + verifyNew(GbpIseConfigListenerImpl.class).withArguments(dataBroker, harvester); + + // close provider check + provider.close(); + Mockito.verify(registration).close(); + } +} \ No newline at end of file diff --git a/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListenerImplTest.java b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListenerImplTest.java new file mode 100644 index 000000000..105c3cb62 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseConfigListenerImplTest.java @@ -0,0 +1,113 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.util.concurrent.Futures; +import java.util.Collections; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +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.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestStatus; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Test for {@link GbpIseConfigListenerImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +public class GbpIseConfigListenerImplTest { + + @Mock + private DataBroker dataBroker; + @Mock + private GbpIseSgtHarvester harvester; + @Mock + private DataTreeModification treeModification; + @Mock + private DataObjectModification dataModification; + @Mock + private WriteTransaction wTx; + @Mock + private IseHarvestConfig config; + + private GbpIseConfigListenerImpl listener; + + @Before + public void setUp() throws Exception { + listener = new GbpIseConfigListenerImpl(dataBroker, harvester); + } + + @Test + public void testOnDataTreeChanged_noop() throws Exception { + Mockito.when(dataModification.getDataAfter()).thenReturn(null); + Mockito.when(treeModification.getRootNode()).thenReturn(dataModification); + + listener.onDataTreeChanged(Collections.singleton(treeModification)); + Mockito.verifyNoMoreInteractions(harvester, dataBroker); + } + + @Test + public void testOnDataTreeChanged_succeeded() throws Exception { + Mockito.when(dataModification.getDataAfter()).thenReturn(config); + Mockito.when(treeModification.getRootNode()).thenReturn(dataModification); + + Mockito.when(harvester.harvest(config)).thenReturn(Futures.immediateFuture(42)); + + Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null)); + Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx); + + listener.onDataTreeChanged(Collections.singleton(treeModification)); + listener.close(); + + final InOrder inOrder = Mockito.inOrder(harvester, dataBroker, wTx); + inOrder.verify(harvester).harvest(config); + inOrder.verify(dataBroker).newWriteOnlyTransaction(); + inOrder.verify(wTx).put(Matchers.eq(LogicalDatastoreType.OPERATIONAL), + Matchers.>any(), + Matchers.any(), + Matchers.eq(true)); + inOrder.verify(wTx).submit(); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testOnDataTreeChanged_failed() throws Exception { + 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(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null)); + Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx); + + listener.onDataTreeChanged(Collections.singleton(treeModification)); + listener.close(); + + final InOrder inOrder = Mockito.inOrder(harvester, dataBroker, wTx); + inOrder.verify(harvester).harvest(config); + inOrder.verify(dataBroker).newWriteOnlyTransaction(); + inOrder.verify(wTx).put(Matchers.eq(LogicalDatastoreType.OPERATIONAL), + Matchers.>any(), + Matchers.any(), + Matchers.eq(true)); + inOrder.verify(wTx).submit(); + inOrder.verifyNoMoreInteractions(); + } +} \ No newline at end of file diff --git a/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvesterImplTest.java b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvesterImplTest.java new file mode 100644 index 000000000..85212b624 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/GbpIseSgtHarvesterImplTest.java @@ -0,0 +1,143 @@ +/* + * 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.gbp_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.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.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Matchers; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.opendaylight.groupbasedpolicy.gbp_ise_adapter.impl.util.RestClientFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.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.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.IseHarvestConfigBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.ise.harvest.config.ConnectionConfigBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.ise.harvest.config.connection.config.HeaderBuilder; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Test for {@link GbpIseSgtHarvesterImpl}. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({RestClientFactory.class}) +public class GbpIseSgtHarvesterImplTest { + + private static final Logger LOG = LoggerFactory.getLogger(GbpIseSgtHarvesterImplTest.class); + + public static final TenantId TENANT_ID = new TenantId("unit-tenant-id-1"); + public static final Uri ISE_REST_URL = new Uri("https://example.org:9060"); + public final String iseReplyAllSgts; + public final String iseReplySgtDetail; + + @Mock + private SgtInfoProcessor processor; + @Mock + private Client client; + @Mock + private WebResource webResource; + @Mock + private WebResource.Builder builder; + @Mock + private ClientResponse response; + + private IseHarvestConfig config; + + 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(); + } + + @Before + public void setUp() throws Exception { + config = new IseHarvestConfigBuilder() + .setTenant(TENANT_ID) + .setConnectionConfig(new ConnectionConfigBuilder() + .setConnectionTimeout(10) + .setReadTimeout(20) + .setHeader(Collections.singletonList(new HeaderBuilder() + .setName("hName") + .setValue("hValue") + .build())) + .setIseRestUrl(ISE_REST_URL) + .build()) + .build(); + + harvester = new GbpIseSgtHarvesterImpl(processor); + } + + @Test + public void testHarvest() throws Exception { + Mockito.when(response.getEntity(String.class)).thenReturn(iseReplyAllSgts, iseReplySgtDetail); + Mockito.when(builder.get(Matchers.>any())).thenReturn(response); + Mockito.when(webResource.getRequestBuilder()).thenReturn(builder); + Mockito.when(webResource.path(Matchers.anyString())).thenReturn(webResource); + Mockito.when(client.resource(Matchers.any())).thenReturn(webResource); + stub(method(RestClientFactory.class, "createIseClient")).toReturn(client); + + Mockito.when(processor.processSgtInfo(Matchers.eq(TENANT_ID), Matchers.>any())).thenReturn( + Futures.immediateCheckedFuture(null)); + + final ListenableFuture harvestResult = harvester.harvest(config); + + final InOrder inOrder = Mockito.inOrder(client, webResource, builder); + inOrder.verify(client).resource(ISE_REST_URL.getValue()); + // all sgts + inOrder.verify(webResource).path("/ers/config/sgt"); + inOrder.verify(webResource).getRequestBuilder(); + inOrder.verify(builder).header(Matchers.anyString(),Matchers.anyString()); + inOrder.verify(builder).get(ClientResponse.class); + // sgt detail + inOrder.verify(webResource).path("/ers/config/sgt/abc123"); + inOrder.verify(webResource).getRequestBuilder(); + inOrder.verify(builder).header(Matchers.anyString(),Matchers.anyString()); + inOrder.verify(builder).get(ClientResponse.class); + inOrder.verifyNoMoreInteractions(); + + final Integer count = harvestResult.get(2, TimeUnit.SECONDS); + Assert.assertEquals(1, count.intValue()); + } +} \ No newline at end of file diff --git a/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEPTemplateGeneratorImplTest.java b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEPTemplateGeneratorImplTest.java new file mode 100644 index 000000000..6f6f0bbea --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEPTemplateGeneratorImplTest.java @@ -0,0 +1,100 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import java.util.Collections; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +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.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.mapper.model.rev160302.SxpMapper; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgt; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointPolicyTemplateBySgtKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.sxp.database.rev160308.Sgt; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Test for {@link SgtToEPTemplateGeneratorImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +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 EPG_NAME_1 = "epg-unit-1"; + public static final Sgt SGT_2 = new Sgt(2); + public static final String EPG_NAME_2 = "epg-unit-2"; + + @Mock + private DataBroker dataBroker; + @Mock + private WriteTransaction wTx; + + private SgtToEPTemplateGeneratorImpl generator; + + @Before + public void setUp() throws Exception { + Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null)); + Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx); + generator = new SgtToEPTemplateGeneratorImpl(dataBroker); + } + + @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 CheckedFuture outcome = + generator.processSgtInfo(TENANT_ID, Lists.newArrayList(sgtInfo1, sgtInfo2)); + + outcome.get(10, TimeUnit.SECONDS); + + final KeyedInstanceIdentifier epTemplatePath1 = + InstanceIdentifier.create(SxpMapper.class) + .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(SGT_1)); + final EndpointPolicyTemplateBySgt epTemplate1 = new EndpointPolicyTemplateBySgtBuilder() + .setSgt(SGT_1) + .setEndpointGroups(Collections.singletonList(new EndpointGroupId(EPG_NAME_1))) + .setTenant(TENANT_ID) + .build(); + + final KeyedInstanceIdentifier epTemplatePath2 = + InstanceIdentifier.create(SxpMapper.class) + .child(EndpointPolicyTemplateBySgt.class, new EndpointPolicyTemplateBySgtKey(SGT_2)); + final EndpointPolicyTemplateBySgt epTemplate2 = new EndpointPolicyTemplateBySgtBuilder() + .setSgt(SGT_2) + .setEndpointGroups(Collections.singletonList(new EndpointGroupId(EPG_NAME_2))) + .setTenant(TENANT_ID) + .build(); + + + final InOrder inOrder = Mockito.inOrder(wTx); + inOrder.verify(wTx, Mockito.calls(1)).put(LogicalDatastoreType.CONFIGURATION, epTemplatePath1, epTemplate1, true); + inOrder.verify(wTx, Mockito.calls(1)).put(LogicalDatastoreType.CONFIGURATION, epTemplatePath2, epTemplate2, false); + inOrder.verify(wTx).submit(); + + Mockito.verifyZeroInteractions(wTx); + + } +} \ No newline at end of file diff --git a/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEpgGeneratorImplTest.java b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEpgGeneratorImplTest.java new file mode 100644 index 000000000..415e35ffb --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/SgtToEpgGeneratorImplTest.java @@ -0,0 +1,96 @@ +/* + * 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.gbp_ise_adapter.impl; + +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.CheckedFuture; +import com.google.common.util.concurrent.Futures; +import java.util.concurrent.TimeUnit; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +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.common.rev140421.TenantId; +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.sxp.database.rev160308.Sgt; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +/** + * Test for {@link SgtToEpgGeneratorImpl}. + */ +@RunWith(MockitoJUnitRunner.class) +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 EPG_NAME_1 = "epg-unit-1"; + public static final Sgt SGT_2 = new Sgt(2); + public static final String EPG_NAME_2 = "epg-unit-2"; + + @Mock + private DataBroker dataBroker; + @Mock + private WriteTransaction wTx; + + private SgtToEpgGeneratorImpl generator; + + @Before + public void setUp() throws Exception { + Mockito.when(wTx.submit()).thenReturn(Futures.immediateCheckedFuture(null)); + Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(wTx); + generator = new SgtToEpgGeneratorImpl(dataBroker); + } + + @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 CheckedFuture outcome = + generator.processSgtInfo(TENANT_ID, Lists.newArrayList(sgtInfo1, sgtInfo2)); + + outcome.get(10, TimeUnit.SECONDS); + + final EndpointGroupId epgId1 = new EndpointGroupId(EPG_NAME_1); + final InstanceIdentifier epgPath1 = IidFactory.endpointGroupIid(TENANT_ID, epgId1); + final EndpointGroup epg1 = createEpg(epgId1, SGT_1.getValue()); + + final EndpointGroupId epgId2 = new EndpointGroupId(EPG_NAME_2); + final InstanceIdentifier epgPath2 = IidFactory.endpointGroupIid(TENANT_ID, epgId2); + final EndpointGroup epg2 = createEpg(epgId2, SGT_2.getValue()); + + final InOrder inOrder = Mockito.inOrder(wTx); + inOrder.verify(wTx, Mockito.calls(1)).put(LogicalDatastoreType.CONFIGURATION, epgPath1, epg1, true); + inOrder.verify(wTx, Mockito.calls(1)).put(LogicalDatastoreType.CONFIGURATION, epgPath2, epg2, false); + inOrder.verify(wTx).submit(); + + Mockito.verifyZeroInteractions(wTx); + } + + private EndpointGroup createEpg(final EndpointGroupId epgId1, final int sgt) { + final String epgIdValue = epgId1.getValue(); + return new EndpointGroupBuilder() + .setId(epgId1) + .setName(new Name(epgIdValue + "--"+sgt)) + .setDescription(new Description("imported from ISE for sgt="+sgt)) + .build(); + } +} \ No newline at end of file diff --git a/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/util/RestClientFactoryTest.java b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/util/RestClientFactoryTest.java new file mode 100644 index 000000000..3a2d69af6 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/java/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/util/RestClientFactoryTest.java @@ -0,0 +1,42 @@ +package org.opendaylight.groupbasedpolicy.gbp_ise_adapter.impl.util; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.client.urlconnection.HTTPSProperties; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.ise.harvest.config.ConnectionConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.gbp.ise.adapter.model.rev160630.gbp.ise.adapter.ise.harvest.config.ConnectionConfigBuilder; + +import javax.net.ssl.SSLSession; +import java.util.Map; + +/** + * Purpose: cover {@link RestClientFactory} + */ +@RunWith(MockitoJUnitRunner.class) +public class RestClientFactoryTest { + + @Mock + private SSLSession sslSession; + + @Test + public void testCreateIseClient() throws Exception { + ConnectionConfig connectionConfig = new ConnectionConfigBuilder() + .setConnectionTimeout(1) + .setReadTimeout(2) + .build(); + + final Client iseClient = RestClientFactory.createIseClient(connectionConfig); + final Map properties = iseClient.getProperties(); + Assert.assertEquals(3, properties.size()); + Assert.assertEquals(1, properties.get("com.sun.jersey.client.property.connectTimeout")); + Assert.assertEquals(2, properties.get("com.sun.jersey.client.property.readTimeout")); + + Assert.assertTrue(properties.get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES) instanceof HTTPSProperties); + final HTTPSProperties httpsProperties = (HTTPSProperties) properties.get(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES); + Assert.assertTrue(httpsProperties.getHostnameVerifier().verify("xxx", sslSession)); + } +} \ No newline at end of file diff --git a/groupbasedpolicy-ise-adapter/src/test/resources/log4j.xml b/groupbasedpolicy-ise-adapter/src/test/resources/log4j.xml new file mode 100644 index 000000000..3dee945a3 --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/resources/log4j.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/groupbasedpolicy-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/rawIse-allSgts.xml b/groupbasedpolicy-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/rawIse-allSgts.xml new file mode 100644 index 000000000..c5dc9296c --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/rawIse-allSgts.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/groupbasedpolicy-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/rawIse-sgtDetail.xml b/groupbasedpolicy-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/rawIse-sgtDetail.xml new file mode 100644 index 000000000..7d3b8806b --- /dev/null +++ b/groupbasedpolicy-ise-adapter/src/test/resources/org/opendaylight/groupbasedpolicy/gbp_ise_adapter/impl/rawIse-sgtDetail.xml @@ -0,0 +1,19 @@ + + + + + + 0 + 42 + diff --git a/pom.xml b/pom.xml index ba05e3a48..90e1c4fd0 100644 --- a/pom.xml +++ b/pom.xml @@ -35,6 +35,7 @@ distribution-karaf features sxp-mapper + groupbasedpolicy-ise-adapter