<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>
<groupId>org.opendaylight.groupbasedpolicy</groupId>
<artifactId>groupbasedpolicy-ui-module</artifactId>
<version>${project.version}</version>
+ <scope>provided</scope>
</dependency>
</dependencies>
<build>
&& renderer.getRendererPolicy().getVersion().equals(version)) {
processingRenderers.remove(configuredRenderer);
Status status = rendererPolicy.getStatus();
- if (status != null && status.getUnconfiguredEndpoints() != null) {
+ if (status != null && status.getUnconfiguredEndpoints() != null
+ && status.getUnconfiguredEndpoints().getUnconfiguredRendererEndpoint() != null
+ && !status.getUnconfiguredEndpoints().getUnconfiguredRendererEndpoint().isEmpty()) {
LOG.warn("Renderer {} did not configure policy with version {} successfully. \n{}",
configuredRenderer.getValue(), version, status);
} else {
<module>distribution-karaf</module>
<module>features</module>
<module>sxp-mapper</module>
+ <module>groupbasedpolicy-ise-adapter</module>
</modules>
<build>
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInputBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocator;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.sff.data.plane.locator.DataPlaneLocator;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.LocatorType;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.Ip;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308.Native;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePath;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServicePathKey;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.LocalBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameBuilder;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfNameKey;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.ConfigServiceChainPathModeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.security.cert.PKIXRevocationChecker;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
return reversedRenderedPath;
}
- /**
- * Method checks up, whether a {@link Local} Service Function Forwarder is present on device or not.
- *
- * @param mountpoint used to access specific device
- * @return true if Local Forwarder is present, false otherwise
- */
- private static boolean checkLocalForwarderPresence(DataBroker mountpoint) {
- InstanceIdentifier<Local> localSffIid = InstanceIdentifier.builder(Native.class)
- .child(ServiceChain.class)
- .child(org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.ServiceFunctionForwarder.class)
- .child(Local.class).build();
- try {
- java.util.Optional<ReadOnlyTransaction> optionalTransaction =
- NetconfTransactionCreator.netconfReadOnlyTransaction(mountpoint);
- if (!optionalTransaction.isPresent()) {
- LOG.warn("Failed to create transaction, mountpoint: {}", mountpoint);
- return false;
- }
- ReadOnlyTransaction transaction = optionalTransaction.get();
- CheckedFuture<Optional<Local>, ReadFailedException> submitFuture =
- transaction.read(LogicalDatastoreType.CONFIGURATION,
- localSffIid);
- Optional<Local> optionalLocalSff = submitFuture.checkedGet();
- transaction.close(); // Release lock
- return optionalLocalSff.isPresent();
- } catch (ReadFailedException e) {
- LOG.warn("Read transaction failed to {} ", e);
- } catch (Exception e) {
- LOG.error("Failed to .. {}", e.getMessage());
- }
- return false;
- }
-
/**
* Method checks up, if some {@link ServicePath} is present on device.
*
static boolean setSfcPart(final ServiceFunctionPath serviceFunctionPath, final RenderedServicePath renderedServicePath,
final RenderedServicePath reversedRenderedServicePath, PolicyWriter policyWriter) {
- if (!checkLocalForwarderPresence(policyWriter.getCurrentMountpoint())) {
- appendLocalSff(policyWriter);
- } else {
- LOG.info("Local forwarder for node {} is already created", policyWriter.getCurrentNodeId());
- }
boolean outcome = true;
// Direct path
final java.util.Optional<RenderedServicePath> renderedServicePathSafe = java.util.Optional.ofNullable(renderedServicePath);
if (!resolveRenderedServicePath(renderedServicePath, policyWriter)) {
outcome = false;
}
- }
- else {
+ } else {
LOG.warn("Rendered service path {} does not contain any hop",
renderedServicePathSafe.map(RenderedServicePath::getName).map(RspName::getValue).orElse("n/a"));
outcome = false;
}
- }
- else {
+ } else {
LOG.warn("Rendered service path is null");
outcome = false;
}
// forwarder (Remote case)
final java.util.Optional<ServiceFunctionForwarder> serviceFunctionForwarder = java.util.Optional.ofNullable(
- SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName));
- return serviceFunctionForwarder.map(sff -> java.util.Optional.ofNullable(IetfModelCodec.ipAddress2010(sff.getIpMgmtAddress()))
- .map(IpAddress::getIpv4Address)
- .map((ipv4Address) -> ipv4Address.getValue())
+ SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName));
+ if (!serviceFunctionForwarder.isPresent()) {
+ LOG.warn("Service function forwarder {} does not exist", sffName.getValue());
+ return false;
+ }
+ final ServiceFunctionForwarder forwarder = serviceFunctionForwarder.get();
+ if (forwarder.getSffDataPlaneLocator() == null || forwarder.getSffDataPlaneLocator().isEmpty()) {
+ LOG.warn("Service function forwarder {} does not contain data plane locator", sffName.getValue());
+ return false;
+ }
+ // TODO only first dpl resolved
+ final SffDataPlaneLocator sffDataPlaneLocator = forwarder.getSffDataPlaneLocator().get(0);
+ final DataPlaneLocator dataPlaneLocator = sffDataPlaneLocator.getDataPlaneLocator();
+ final LocatorType locatorType = dataPlaneLocator.getLocatorType();
+ if (locatorType != null && locatorType instanceof Ip) {
+ final IpAddress remoteForwarderIpAddress = IetfModelCodec.ipAddress2010(((Ip) locatorType).getIp());
+ if (remoteForwarderIpAddress == null || remoteForwarderIpAddress.getIpv4Address() == null) {
+ LOG.warn("Service function forwarder {} data plane locator does not contain ip address", sffName.getValue());
+ return false;
+ }
+ final String remoteForwarderStringIp = remoteForwarderIpAddress.getIpv4Address().getValue();
+ return serviceFunctionForwarder.map(sff -> java.util.Optional.ofNullable(sff.getIpMgmtAddress())
+ .map(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress::getIpv4Address)
+ .map(Ipv4Address::getValue)
.map(addressValue -> {
// Set up choice. If remote, this choice is overwritten
final ServiceTypeChoice serviceTypeChoice;
final ServiceFfNameBuilder remoteSffBuilder = new ServiceFfNameBuilder();
remoteSffBuilder.setName(sffName.getValue())
.setKey(new ServiceFfNameKey(sffName.getValue()))
- .setIp(new IpBuilder().setAddress(new Ipv4Address(addressValue)).build());
+ .setIp(new IpBuilder().setAddress(new Ipv4Address(remoteForwarderStringIp)).build());
policyWriter.cache(remoteSffBuilder.build());
serviceTypeChoice = forwarderTypeChoice(sffName.getValue());
} else {
).orElseGet(createNegativePathWithLogSupplier(sffName.getValue(),
(value) -> LOG.error("Sff with name {} does not exist", value))
);
- }
-
- private static void appendLocalSff(final PolicyWriter policyWriter) {
- final LocalBuilder localSffBuilder = new LocalBuilder();
- localSffBuilder.setIp(new IpBuilder().setAddress(new Ipv4Address(policyWriter.getManagementIpAddress()))
- .build());
- policyWriter.cache(localSffBuilder.build());
+ }
+ return false;
}
static ServiceTypeChoice forwarderTypeChoice(final String forwarderName) {
private static void checkSfcRspStatus(final RspName rspName, final DataBroker dataBroker) {
/** TODO A better way to do this is to register listener and wait for notification than using hardcoded timeout
* with Thread.sleep(). Example in class BridgeDomainManagerImpl
- */
+ */
ConfiguredRenderedPath renderedPath = null;
LOG.info("Waiting for SFC to configure path {} ...", rspName.getValue());
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.Local;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.function.forwarder.ServiceFfName;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.slf4j.Logger;
private final String interfaceName;
private final String policyMapName;
private final String managementIpAddress;
- private Local localForwarder;
public PolicyWriter(final DataBroker dataBroker, final String interfaceName, final String ipAddress,
final String policyMapName, final NodeId nodeId) {
this.policyMapEntries.addAll(policyMapEntries);
}
- public void cache(Local localForwarder) {
- this.localForwarder = localForwarder;
- }
-
public void cache(ServiceFfName remoteForwarder) {
remoteForwarders.add(remoteForwarder);
}
public CheckedFuture<Boolean, TransactionCommitFailedException> commitToDatastore() {
LOG.info("Configuring policy on node {} ... ", nodeId.getValue());
// SFC
- boolean localResult = PolicyWriterUtil.writeLocal(localForwarder, nodeId, mountpoint);
boolean remoteResult = PolicyWriterUtil.writeRemote(remoteForwarders, nodeId, mountpoint);
boolean servicePathsResult = PolicyWriterUtil.writeServicePaths(serviceChains, nodeId, mountpoint);
// GBP - maintain order!
boolean interfaceResult = PolicyWriterUtil.writeInterface(policyMapName, interfaceName, nodeId, mountpoint);
// Result
LOG.info("Policy configuration on node {} completed", nodeId.getValue());
- return Futures.immediateCheckedFuture(classMapResult && policyMapResult && interfaceResult && localResult
- && remoteResult && servicePathsResult);
+ return Futures.immediateCheckedFuture(classMapResult && policyMapResult && interfaceResult && remoteResult
+ && servicePathsResult);
}
public CheckedFuture<Boolean, TransactionCommitFailedException> removeFromDatastore() {
// TODO remove class map?
// SFC
boolean servicePathsResult = PolicyWriterUtil.removeServicePaths(serviceChains, nodeId, mountpoint);
- boolean localResult = PolicyWriterUtil.removeLocal(nodeId, mountpoint);
// TODO remove remote forwarders
// Result
LOG.info("Policy removed from node {}", nodeId.getValue());
- return Futures.immediateCheckedFuture(classMapResult && policyMapEntriesResult && servicePathsResult
- && localResult);
+ return Futures.immediateCheckedFuture(classMapResult && policyMapEntriesResult && servicePathsResult);
}
public String getManagementIpAddress() {
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.RenderedServicePathBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHop;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.rendered.service.paths.rendered.service.path.RenderedServicePathHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.SffDataPlaneLocatorBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarder.base.sff.data.plane.locator.DataPlaneLocatorBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarderBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPaths;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.ServiceFunctionPathsBuilder;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPath;
import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sfp.rev140701.service.function.paths.ServiceFunctionPathBuilder;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sl.rev140701.data.plane.locator.locator.type.IpBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* Test for {@link ServiceChainingUtil}.
*/
@Test
public void testSetSfcPart_success() throws Exception {
final RenderedServicePath rsp = createRsp("unit-rsp-03");
+ final DataPlaneLocatorBuilder dataPlaneLocatorBuilder = new DataPlaneLocatorBuilder();
+ final IpBuilder ipBuilderLocatorType = new IpBuilder();
+ ipBuilderLocatorType.setIp(IetfModelCodec.ipAddress2013(new IpAddress(new Ipv4Address("1.2.3.4"))));
+ dataPlaneLocatorBuilder.setLocatorType(ipBuilderLocatorType.build());
+ final SffDataPlaneLocatorBuilder sffDataPlaneLocatorBuilder = new SffDataPlaneLocatorBuilder();
+ sffDataPlaneLocatorBuilder.setDataPlaneLocator(dataPlaneLocatorBuilder.build());
final org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder
sff = new ServiceFunctionForwarderBuilder()
.setName(new SffName("unit-sff-03"))
.setIpMgmtAddress(IetfModelCodec.ipAddress2013(new IpAddress(new Ipv4Address("1.2.3.4"))))
+ .setSffDataPlaneLocator(Collections.singletonList(sffDataPlaneLocatorBuilder.build()))
.build();
final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
sfpBuilder.setSymmetric(false);
final ServiceFunctionPath sfp = sfpBuilder.build();
- stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
-
PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(sff);
Mockito.verify(policyWriter).cache(Matchers.<ServiceFfName>any());
Mockito.verify(policyWriter).cache(Matchers.<ServiceChain>any());
- Mockito.verify(policyWriter).getCurrentNodeId();
- Mockito.verify(policyWriter).getCurrentMountpoint();
Mockito.verify(policyWriter).getManagementIpAddress();
Mockito.verifyNoMoreInteractions(policyWriter);
}
@Test
public void testSetSfcPart_success_newRsp() throws Exception {
final RenderedServicePath rsp = createRsp("unit-rsp-03");
+ final DataPlaneLocatorBuilder dataPlaneLocatorBuilder = new DataPlaneLocatorBuilder();
+ final IpBuilder ipBuilderLocatorType = new IpBuilder();
+ ipBuilderLocatorType.setIp(IetfModelCodec.ipAddress2013(new IpAddress(new Ipv4Address("1.2.3.4"))));
+ dataPlaneLocatorBuilder.setLocatorType(ipBuilderLocatorType.build());
+ final SffDataPlaneLocatorBuilder sffDataPlaneLocatorBuilder = new SffDataPlaneLocatorBuilder();
+ sffDataPlaneLocatorBuilder.setDataPlaneLocator(dataPlaneLocatorBuilder.build());
final org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder
sff = new ServiceFunctionForwarderBuilder()
.setName(new SffName("unit-sff-03"))
.setIpMgmtAddress(IetfModelCodec.ipAddress2013(new IpAddress(new Ipv4Address("1.2.3.4"))))
+ .setSffDataPlaneLocator(Collections.singletonList(sffDataPlaneLocatorBuilder.build()))
.build();
final ServiceFunctionPathBuilder sfpBuilder = new ServiceFunctionPathBuilder();
sfpBuilder.setSymmetric(false);
final ServiceFunctionPath sfp = sfpBuilder.build();
- stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(false);
-
PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(sff);
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
Assert.assertTrue(outcome);
- Mockito.verify(policyWriter).cache(Matchers.<Local>any());
Mockito.verify(policyWriter).cache(Matchers.<ServiceFfName>any());
Mockito.verify(policyWriter).cache(Matchers.<ServiceChain>any());
- Mockito.verify(policyWriter).getCurrentMountpoint();
- Mockito.verify(policyWriter, Mockito.times(2)).getManagementIpAddress();
+ Mockito.verify(policyWriter).getManagementIpAddress();
Mockito.verifyNoMoreInteractions(policyWriter);
}
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
Assert.assertFalse(outcome);
- Mockito.verify(policyWriter).getCurrentMountpoint();
- Mockito.verify(policyWriter).getManagementIpAddress();
- Mockito.verify(policyWriter).cache(Matchers.<Local>any());
Mockito.verifyNoMoreInteractions(policyWriter);
}
sfpBuilder.setSymmetric(false);
final ServiceFunctionPath sfp = sfpBuilder.build();
- stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
-
PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
- Mockito.verify(policyWriter).getCurrentMountpoint();
- Mockito.verify(policyWriter).getCurrentNodeId();
Mockito.verifyNoMoreInteractions(policyWriter);
}
sfpBuilder.setSymmetric(false);
final ServiceFunctionPath sfp = sfpBuilder.build();
- stub(method(ServiceChainingUtil.class, "checkLocalForwarderPresence")).toReturn(true);
-
PowerMockito.mockStatic(SfcProviderServiceForwarderAPI.class);
final SfcProviderServiceForwarderAPI api = PowerMockito.mock(SfcProviderServiceForwarderAPI.class);
PowerMockito.when(api.readServiceFunctionForwarder(sffNameCaptor.capture())).thenReturn(
Assert.assertEquals("rsp-hop-01-sf+sff", sffNameCaptor.getValue().getValue());
- Mockito.verify(policyWriter).getCurrentMountpoint();
- Mockito.verify(policyWriter).getCurrentNodeId();
Mockito.verifyNoMoreInteractions(policyWriter);
}
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.JdkFutureAdapters;
import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Collections;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointReg;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.register.endpoint.input.AddressEndpointRegBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.groupbasedpolicy.sxp.mapper.model.rev160302.sxp.mapper.EndpointForwardingTemplateBySubnet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collections;
+
/**
* Purpose: exclusively processes sxp master database changes and EGP templates changes
*/
@Override
public ListenableFuture<RpcResult<Void>> apply(final Optional<AddressEndpoint> input) throws Exception {
final ListenableFuture<RpcResult<Void>> nextResult;
- if (input == null || !input.isPresent()) {
+ if (input == null || !input.isPresent() || !isSameEpg(epInput, input.get())) {
// invoke service
return JdkFutureAdapters.listenInPoolThread(l3EndpointService.registerEndpoint(epInput));
} else {
});
}
+ private boolean isSameEpg(RegisterEndpointInput epInput, AddressEndpoint input) {
+ if (epInput == null || epInput.getAddressEndpointReg() == null || epInput.getAddressEndpointReg().isEmpty()) {
+ return true;
+ }
+ final AddressEndpointReg epInputAddressEndpoint = epInput.getAddressEndpointReg().get(0);
+ if (epInputAddressEndpoint.getEndpointGroup() == null || epInputAddressEndpoint.getEndpointGroup().isEmpty()) {
+ return true;
+ }
+ if (input == null || input.getEndpointGroup() == null || input.getEndpointGroup().isEmpty()) {
+ return true;
+ }
+ final EndpointGroupId addressEndpointGroupId = epInputAddressEndpoint.getEndpointGroup().get(0);
+ final EndpointGroupId existingEndpointGroupId = input.getEndpointGroup().get(0);
+ return addressEndpointGroupId.equals(existingEndpointGroupId);
+ }
+
}