<artifactId>sxp-mapper</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>groupbasedpolicy-ise-adapter</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<!-- GBP configuration -->
<dependency>
<type>xml</type>
<classifier>config</classifier>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>groupbasedpolicy-ise-adapter</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
<!-- GBP features -->
<groupId>org.opendaylight.groupbasedpolicy</groupId>
<artifactId>ios-xe-renderer</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy-ise-adapter</artifactId>
+ </dependency>
<!-- GBP configuration -->
<dependency>
<type>xml</type>
<classifier>config</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy-ise-adapter</artifactId>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </dependency>
</dependencies>
</project>
<configfile finalname="${config.configfile.directory}/15-l2-l3-domain-extension.xml">mvn:org.opendaylight.groupbasedpolicy/l2-l3-domain-extension/{{VERSION}}/xml/config</configfile>
<configfile finalname="${config.configfile.directory}/15-groupbasedpolicy-ios-xe-renderer.xml">mvn:org.opendaylight.groupbasedpolicy/ios-xe-renderer/{{VERSION}}/xml/config</configfile>
</feature>
+
+ <!--
+ GBP-ISE ADAPTER
+ -->
+ <feature name='odl-groupbasedpolicy-ise-adapter' version='${project.version}' description='OpenDaylight :: groupbasedpolicy :: gbp-ise adapter'>
+ <feature version="${project.version}">odl-groupbasedpolicy-sxp-mapper</feature>
+ <feature version="${sxp.version}">odl-sxp-core</feature>
+ <bundle>mvn:commons-net/commons-net/{{VERSION}}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-client/{{VERSION}}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-core/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-ise-adapter/{{VERSION}}</bundle>
+ <configfile finalname="${config.configfile.directory}/16-groupbasedpolicy-ise-adapter.xml">mvn:org.opendaylight.groupbasedpolicy/groupbasedpolicy-ise-adapter/{{VERSION}}/xml/config</configfile>
+ </feature>
</features>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy-ise-adapter</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+ <name>groupbasedpolicy-ise-adapter</name>
+
+ <properties>
+ <sxp.version>1.3.0-SNAPSHOT</sxp.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>groupbasedpolicy-artifacts</artifactId>
+ <version>${project.version}</version>
+ <scope>import</scope>
+ <type>pom</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.sxp</groupId>
+ <artifactId>sxp-api</artifactId>
+ <version>${sxp.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- model dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.groupbasedpolicy</groupId>
+ <artifactId>sxp-mapper</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.sxp</groupId>
+ <artifactId>sxp-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+
+ <!-- util -->
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ </dependency>
+
+ <!-- testing dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <!-- project build -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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
+ -->
+
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+
+<snapshot>
+ <configuration>
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:gbp-ise-adapter="urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:gbp-ise-adapter">
+ gbp-ise-adapter:gbp-ise-adapter-impl
+ </type>
+ <name>gbp-ise-adapter</name>
+
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+ <name>binding-data-broker</name>
+ </data-broker>
+ <broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </broker>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:gbp-ise-adapter?module=gbp-ise-adapter-cfg&revision=2016-06-30</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:groupbasedpolicy:gbp-ise-adapter:model?module=gbp-ise-adapter-model&revision=2016-06-30</capability>
+ </required-capabilities>
+
+</snapshot>
--- /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.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());
+ }
+
+}
--- /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
+ */
+
+/*
+* 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 {
+
+}
--- /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.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<DataTreeChangeListener<IseHarvestConfig>> 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<IseHarvestConfig> dataTreePath = new DataTreeIdentifier<>(
+ LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(GbpIseAdapter.class).child(IseHarvestConfig.class));
+
+ // register config listener
+ registration = dataBroker.registerDataTreeChangeListener(dataTreePath,
+ gbpIseConfigListener);
+
+ LOG.info("Started");
+ }
+}
--- /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.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<IseHarvestConfig>, AutoCloseable {
+ // nobody
+}
--- /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.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<DataTreeModification<IseHarvestConfig>> collection) {
+ for (DataTreeModification<IseHarvestConfig> modification : collection) {
+ final IseHarvestConfig iseHarvestConfig = modification.getRootNode().getDataAfter();
+ if (iseHarvestConfig != null) {
+ pool.submit(() -> {
+ final ListenableFuture<Integer> harvestResult = gbpIseSgtHarvester.harvest(iseHarvestConfig);
+ Futures.addCallback(harvestResult, new FutureCallback<Integer>() {
+ @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<Void, TransactionCommitFailedException> storeOutcome(final boolean succeeded, final int counter, final String reason) {
+ final WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
+ final InstanceIdentifier<IseHarvestStatus> 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();
+ }
+ }
+ }
+}
--- /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.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<Integer> harvest(@Nonnull IseHarvestConfig configuration);
+}
--- /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.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<Integer> harvest(@Nonnull final IseHarvestConfig configuration) {
+ final ConnectionConfig connectionConfig = configuration.getConnectionConfig();
+ ListenableFuture<Integer> 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<SgtInfo> sgtInfos = harvestDetails(rawSgtSummary, baseWebResource, connectionConfig.getHeader());
+
+ ListenableFuture<Void> processingResult = Futures.immediateCheckedFuture(null);
+ for (SgtInfoProcessor processor : sgtInfoProcessors) {
+ processingResult = Futures.transform(processingResult, new AsyncFunction<Void, Void>() {
+ @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);
+ }
+ });
+ }
+ result = Futures.transform(processingResult, new Function<Void, Integer>() {
+ @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<Header> 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<SgtInfo> harvestDetails(final String rawSgtSummary, final WebResource baseWebResource, final List<Header> headers) {
+ LOG.trace("rawSgtSummary: {}", rawSgtSummary);
+ final List<SgtInfo> 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;
+ }
+}
--- /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.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;
+ }
+}
--- /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.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<Void, TransactionCommitFailedException> processSgtInfo(final TenantId tenant, List<SgtInfo> sgtInfos);
+}
--- /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.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<Void, TransactionCommitFailedException> processSgtInfo(final TenantId tenantId, final List<SgtInfo> 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<EndpointPolicyTemplateBySgt> 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();
+ }
+}
--- /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.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<Void, TransactionCommitFailedException> processSgtInfo(final TenantId tenantId, final List<SgtInfo> 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<EndpointGroup> 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();
+ }
+}
--- /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.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
+ ));
+ }
+}
--- /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
+ */
+
+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;
+ }
+ }
+ }
+
+ }
+ }
+}
--- /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
+ */
+
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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<GbpIseConfigListener> 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.<DataTreeIdentifier<IseHarvestConfig>>any(),
+ Matchers.<GbpIseConfigListener>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
--- /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.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<IseHarvestConfig> treeModification;
+ @Mock
+ private DataObjectModification<IseHarvestConfig> 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.<InstanceIdentifier<IseHarvestStatus>>any(),
+ Matchers.<IseHarvestStatus>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.<InstanceIdentifier<IseHarvestStatus>>any(),
+ Matchers.<IseHarvestStatus>any(),
+ Matchers.eq(true));
+ inOrder.verify(wTx).submit();
+ inOrder.verifyNoMoreInteractions();
+ }
+}
\ No newline at end of file
--- /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.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.<Class<ClientResponse>>any())).thenReturn(response);
+ Mockito.when(webResource.getRequestBuilder()).thenReturn(builder);
+ Mockito.when(webResource.path(Matchers.anyString())).thenReturn(webResource);
+ Mockito.when(client.resource(Matchers.<String>any())).thenReturn(webResource);
+ stub(method(RestClientFactory.class, "createIseClient")).toReturn(client);
+
+ Mockito.when(processor.processSgtInfo(Matchers.eq(TENANT_ID), Matchers.<List<SgtInfo>>any())).thenReturn(
+ Futures.immediateCheckedFuture(null));
+
+ final ListenableFuture<Integer> 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
--- /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.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<Void, TransactionCommitFailedException> outcome =
+ generator.processSgtInfo(TENANT_ID, Lists.newArrayList(sgtInfo1, sgtInfo2));
+
+ outcome.get(10, TimeUnit.SECONDS);
+
+ final KeyedInstanceIdentifier<EndpointPolicyTemplateBySgt, EndpointPolicyTemplateBySgtKey> 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<EndpointPolicyTemplateBySgt, EndpointPolicyTemplateBySgtKey> 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
--- /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.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<Void, TransactionCommitFailedException> outcome =
+ generator.processSgtInfo(TENANT_ID, Lists.newArrayList(sgtInfo1, sgtInfo2));
+
+ outcome.get(10, TimeUnit.SECONDS);
+
+ final EndpointGroupId epgId1 = new EndpointGroupId(EPG_NAME_1);
+ final InstanceIdentifier<EndpointGroup> epgPath1 = IidFactory.endpointGroupIid(TENANT_ID, epgId1);
+ final EndpointGroup epg1 = createEpg(epgId1, SGT_1.getValue());
+
+ final EndpointGroupId epgId2 = new EndpointGroupId(EPG_NAME_2);
+ final InstanceIdentifier<EndpointGroup> 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
--- /dev/null
+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<String, Object> 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
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<!--\r
+ ~ Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
+ ~\r
+ ~ This program and the accompanying materials are made available under the\r
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ -->\r
+\r
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">\r
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">\r
+\r
+ <appender name="console" class="org.apache.log4j.ConsoleAppender">\r
+ <layout class="org.apache.log4j.PatternLayout">\r
+ <param name="ConversionPattern" value="%-6p %d{HH:mm:ss.SSS} [%10.10t] %30.30c %x - %m%n"/>\r
+ </layout>\r
+ <!-- <param name="Threshold" value="DEBUG" /> -->\r
+ </appender>\r
+\r
+ <logger name="org.opendaylight.groupbasedpolicy.gbp_ise_adapter.impl" additivity="false">\r
+ <level value="TRACE"/>\r
+ <appender-ref ref="console"/>\r
+ </logger>\r
+\r
+ <root>\r
+ <priority value="INFO"/>\r
+ <appender-ref ref="console"/>\r
+ </root>\r
+</log4j:configuration>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ ~ Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ ~
+ ~ This program and the accompanying materials are made available under the
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+ -->
+
+<ns3:searchResult xmlns:ns5="ers.ise.cisco.com"
+ xmlns:ns3="v2.ers.ise.cisco.com"
+ total="1">
+ <ns3:nextPage rel="next" href="" type="application/xml"/>
+ <ns3:resources>
+ <ns5:resource description="" id="abc123" name="boss_group">
+ <link rel="self" href="https://example.org:9060/ers/config/sgt/abc123" type="application/xml"/>
+ </ns5:resource>
+ </ns3:resources>
+</ns3:searchResult>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<!--
+ ~ Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
+ ~
+ ~ This program and the accompanying materials are made available under the
+ ~ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ ~ and is available at http://www.eclipse.org/legal/epl-v10.html
+ -->
+
+<ns4:sgt xmlns:ers="ers.ise.cisco.com"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:ns4="trustsec.ers.ise.cisco.com"
+ description=""
+ id="abc123"
+ name="boss-group">
+ <link rel="self" href="https://example.com:9060/ers/config/sgt/abc123" type="application/xml"/>
+ <generationId>0</generationId>
+ <value>42</value>
+</ns4:sgt>
<module>distribution-karaf</module>
<module>features</module>
<module>sxp-mapper</module>
+ <module>groupbasedpolicy-ise-adapter</module>
</modules>
<build>