ios-xe renderer - policy manager + mapper 84/39184/13
authorVladimir Lavor <vlavor@cisco.com>
Mon, 23 May 2016 14:26:49 +0000 (16:26 +0200)
committerVladimir Lavor <vlavor@cisco.com>
Thu, 26 May 2016 10:11:59 +0000 (12:11 +0200)
- policy manager create case
- class-map mapping
- first hop sff
- added PolicyManager interface
- node listener

Signed-off-by: Vladimir Lavor <vlavor@cisco.com>
Change-Id: Ifd1ef7a312927c442aecf02cc04c0ae9acfb1de7

26 files changed:
renderers/ios-xe/pom.xml
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/api/manager/PolicyManager.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/IosXeRendererProviderImpl.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/IosXeCapableNodeListenerImpl.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/RendererConfigurationListenerImpl.java
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/NodeManager.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImpl.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyMapper.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/NodeWriter.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyManagerUtil.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyWriter.java [new file with mode: 0644]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/ClassNameTypeBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/ClassNameTypeBuilder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/CosValueTypeBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/CosValueTypeBuilder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/DscpTypeBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/DscpTypeBuilder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/ExpValueTypeBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/ExpValueTypeBuilder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/PrecValueTypeBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/PrecValueTypeBuilder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/PrecedenceType2Builder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/PrecedenceType2Builder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/PrecedenceTypeBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/PrecedenceTypeBuilder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/QosValueTypeBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/QosValueTypeBuilder.java with 92% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/_native/mls/qos/MapPolicedDscpBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/_native/mls/qos/MapPolicedDscpBuilder.java with 85% similarity]
renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160308/_native/policy/map/_class/pm/policy/monitor/metric/rtp/ClockRateNumberBuilder.java [moved from renderers/ios-xe/src/main/java/org/opendaylight/yang/gen/v1/urn/ios/rev160516/_native/policy/map/_class/pm/policy/monitor/metric/rtp/ClockRateNumberBuilder.java with 86% similarity]
renderers/ios-xe/src/main/yang/netconf/ned.yang
renderers/ios-xe/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/RendererConfigurationListenerImplTest.java
renderers/ios-xe/src/test/resources/log4j.xml [new file with mode: 0644]
renderers/ofoverlay/pom.xml
renderers/pom.xml

index 7678cc58d810877150f26da3cc4e16753f9206c6..ba40c2ecb98c4545f1791bc11cffec2009bd272d 100755 (executable)
   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>
+    <modelVersion>4.0.0</modelVersion>
 
-  <parent>
-    <groupId>org.opendaylight.groupbasedpolicy</groupId>
-    <artifactId>groupbasedpolicy-renderers</artifactId>
-    <version>0.4.0-SNAPSHOT</version>
-    <relativePath>../</relativePath>
-  </parent>
+    <parent>
+        <groupId>org.opendaylight.groupbasedpolicy</groupId>
+        <artifactId>groupbasedpolicy-renderers</artifactId>
+        <version>0.4.0-SNAPSHOT</version>
+        <relativePath>../</relativePath>
+    </parent>
 
-  <artifactId>ios-xe-renderer</artifactId>
-  <packaging>bundle</packaging>
+    <artifactId>ios-xe-renderer</artifactId>
+    <packaging>bundle</packaging>
 
-  <dependencies>
-    <!-- model dependencies -->
-    <dependency>
-      <groupId>org.opendaylight.groupbasedpolicy</groupId>
-      <artifactId>sxp-mapper</artifactId>
-    </dependency>
+    <properties>
+        <netconf.version>1.1.0-SNAPSHOT</netconf.version>
+    </properties>
 
-    <!-- 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.opendaylight.controller</groupId>
-      <artifactId>sal-binding-broker-impl</artifactId>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.opendaylight.groupbasedpolicy</groupId>
-      <artifactId>groupbasedpolicy</artifactId>
-      <version>${project.version}</version>
-      <type>test-jar</type>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.opendaylight.netconf</groupId>
+                <artifactId>netconf-artifacts</artifactId>
+                <version>${netconf.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.opendaylight.controller</groupId>
+                <artifactId>mdsal-artifacts</artifactId>
+                <version>${mdsal.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
 
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.opendaylight.yangtools</groupId>
-        <artifactId>yang-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <id>config</id>
-            <goals>
-              <goal>generate-sources</goal>
-            </goals>
-            <configuration>
-              <codeGenerators>
-                <generator>
-                  <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
-                  <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
-                  <additionalConfiguration>
-                    <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
-                    <namespaceToPackage2>urn:opendaylight:params:xml:ns:yang:groupbasedpolicy:renderer==org.opendaylight.groupbasedpolicy.renderer</namespaceToPackage2>
-                  </additionalConfiguration>
-                </generator>
-              </codeGenerators>
-              <inspectDependencies>true</inspectDependencies>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
+    <dependencies>
+        <!-- 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.opendaylight.controller</groupId>
+            <artifactId>sal-binding-broker-impl</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.groupbasedpolicy</groupId>
+            <artifactId>groupbasedpolicy</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.sfc</groupId>
+            <artifactId>sfc-model</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.groupbasedpolicy</groupId>
+            <artifactId>sxp-mapper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.sfc</groupId>
+            <artifactId>sfc-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.controller.model</groupId>
+            <artifactId>model-inventory</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.netconf</groupId>
+            <artifactId>sal-netconf-connector</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>config</id>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                                    <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+                                    <additionalConfiguration>
+                                        <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                                        <namespaceToPackage2>urn:opendaylight:params:xml:ns:yang:groupbasedpolicy:renderer==org.opendaylight.groupbasedpolicy.renderer</namespaceToPackage2>
+                                    </additionalConfiguration>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/api/manager/PolicyManager.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/api/manager/PolicyManager.java
new file mode 100644 (file)
index 0000000..7774d8c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.renderer.ios_xe_provider.api.manager;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
+
+/**
+ * Purpose: general policy manager prescription
+ */
+public interface PolicyManager extends AutoCloseable {
+
+    /**
+     * synchronize given configuration with device
+     *  @param dataBefore
+     * @param dataAfter
+     */
+    ListenableFuture<Boolean> syncPolicy(Configuration dataBefore, Configuration dataAfter);
+
+    @Override
+    void close();
+}
index c43c41e49353d92ffb18b181d317a8b8a4e05994..e4b042eb4461dac63818af89b2f18da38d6929bf 100644 (file)
@@ -15,7 +15,10 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.IosXeRendererProvider;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyCacheImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.EpPolicyTemplateBySgtListenerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.IosXeCapableNodeListenerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener.RendererConfigurationListenerImpl;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.NodeManager;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -31,7 +34,10 @@ public class IosXeRendererProviderImpl implements IosXeRendererProvider, Binding
     private final RendererName rendererName;
     private RendererConfigurationListenerImpl rendererConfigurationListener;
     private EpPolicyTemplateBySgtListenerImpl epPolicyTemplateBySgtListener;
+    private IosXeCapableNodeListenerImpl iosXeCapableNodeListener;
     private EpPolicyCacheImpl epPolicyCache;
+    private PolicyManagerImpl policyManager;
+    private NodeManager nodeManager;
 
     public IosXeRendererProviderImpl(final DataBroker dataBroker, final BindingAwareBroker broker,
                                      final RendererName rendererName) {
@@ -51,6 +57,9 @@ public class IosXeRendererProviderImpl implements IosXeRendererProvider, Binding
         if (epPolicyTemplateBySgtListener != null) {
             epPolicyTemplateBySgtListener.close();
         }
+        if (iosXeCapableNodeListener != null) {
+            iosXeCapableNodeListener.close();
+        }
         if (epPolicyCache != null) {
             epPolicyCache.invalidateAll();
         }
@@ -60,11 +69,17 @@ public class IosXeRendererProviderImpl implements IosXeRendererProvider, Binding
     public void onSessionInitiated(final BindingAwareBroker.ProviderContext providerContext) {
         LOG.info("starting ios-xe renderer");
         //TODO register listeners:
+        // node-manager
+        nodeManager = new NodeManager(dataBroker, providerContext);
         // ep-policy-template-by-sgt
         epPolicyCache = new EpPolicyCacheImpl();
         epPolicyTemplateBySgtListener = new EpPolicyTemplateBySgtListenerImpl(dataBroker, epPolicyCache);
+        // network-topology
+        iosXeCapableNodeListener = new IosXeCapableNodeListenerImpl(dataBroker, nodeManager);
+        // policy-manager
+        policyManager = new PolicyManagerImpl(dataBroker, epPolicyCache);
         // renderer-configuration endpoints
-        rendererConfigurationListener = new RendererConfigurationListenerImpl(dataBroker, rendererName, epPolicyCache);
+        rendererConfigurationListener = new RendererConfigurationListenerImpl(dataBroker, rendererName, policyManager);
         // supported node list maintenance
         // TODO: upkeep of available renderer-nodes
     }
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/IosXeCapableNodeListenerImpl.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/listener/IosXeCapableNodeListenerImpl.java
new file mode 100644 (file)
index 0000000..9cb7194
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
+
+import com.google.common.base.Preconditions;
+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.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.NodeManager;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.Collection;
+
+import static org.opendaylight.sfc.provider.SfcProviderDebug.printTraceStart;
+
+public class IosXeCapableNodeListenerImpl implements DataTreeChangeListener<NetworkTopology>, AutoCloseable {
+
+    private static final Logger LOG = LoggerFactory.getLogger(IosXeCapableNodeListenerImpl.class);
+    private final NodeManager nodeManager;
+
+    private final ListenerRegistration listenerRegistration;
+
+
+    public IosXeCapableNodeListenerImpl(final DataBroker dataBroker, final NodeManager nodeManager) {
+        this.nodeManager = Preconditions.checkNotNull(nodeManager);
+        final DataTreeIdentifier<NetworkTopology> networkTopologyPath = new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL,
+                InstanceIdentifier.builder(NetworkTopology.class).build());
+        listenerRegistration = Preconditions.checkNotNull(dataBroker
+                .registerDataTreeChangeListener(networkTopologyPath, this));
+        LOG.info("network-topology listener registered");
+    }
+
+    @Override
+    public void onDataTreeChanged(@Nonnull Collection<DataTreeModification<NetworkTopology>> changes) {
+        printTraceStart(LOG);
+        for (DataTreeModification<NetworkTopology> modification : changes) {
+            DataObjectModification<NetworkTopology> rootNode = modification.getRootNode();
+            NetworkTopology dataAfter = rootNode.getDataAfter();
+            NetworkTopology dataBefore = rootNode.getDataBefore();
+            if (dataAfter != null && dataBefore == null) {
+                nodeManager.syncNodes(dataAfter.getTopology(), null);
+            }
+            else if (dataAfter == null && dataBefore != null) {
+                nodeManager.syncNodes(null, dataBefore.getTopology());
+            }
+            else if (dataAfter != null) {
+                nodeManager.syncNodes(dataAfter.getTopology(), dataBefore.getTopology());
+            }
+        }
+    }
+
+    @Override
+    public void close() {
+        listenerRegistration.close();
+    }
+}
index c5cc7172a088463dd5a17e125c573ebdbf683141..26bdff8999b3d5fd60db313b51a5b8be400c00f8 100644 (file)
@@ -9,33 +9,26 @@
 package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.listener;
 
 import com.google.common.base.Preconditions;
-import java.util.Collection;
-import javax.annotation.Nonnull;
 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.DataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
-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.sxp.database.rev160308.Sgt;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.annotation.Nonnull;
+import java.util.Collection;
+
 /**
  * Purpose: process changes of configured renderer policies
  */
@@ -43,11 +36,11 @@ public class RendererConfigurationListenerImpl implements DataTreeChangeListener
 
     private static final Logger LOG = LoggerFactory.getLogger(RendererConfigurationListenerImpl.class);
     private final ListenerRegistration<RendererConfigurationListenerImpl> listenerRegistration;
-    private final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache;
+    private final PolicyManager policyManager;
 
     public RendererConfigurationListenerImpl(final DataBroker dataBroker, final RendererName rendererName,
-                                             final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache) {
-        this.epPolicyCache = Preconditions.checkNotNull(epPolicyCache, "missing endpoint template cache");
+                                             final PolicyManager policyManager) {
+        this.policyManager = Preconditions.checkNotNull(policyManager, "missing endpoint template cache");
         final InstanceIdentifier<RendererPolicy> policyPath = InstanceIdentifier.create(Renderers.class)
                 .child(Renderer.class, new RendererKey(rendererName))
                 .child(RendererPolicy.class);
@@ -65,22 +58,16 @@ public class RendererConfigurationListenerImpl implements DataTreeChangeListener
         for (DataTreeModification<RendererPolicy> rendererPolicyDataTreeModification : collection) {
             final DataObjectModification<RendererPolicy> rootNode = rendererPolicyDataTreeModification.getRootNode();
 
+            final RendererPolicy dataBefore = rootNode.getDataBefore();
             final RendererPolicy dataAfter = rootNode.getDataAfter();
-            if (dataAfter != null && dataAfter.getConfiguration() != null) {
-                // find sgt
-                final Configuration configuration = dataAfter.getConfiguration();
-                for (RendererEndpoint rendererEndpoint : configuration.getRendererEndpoints().getRendererEndpoint()) {
-                    // lookup endpoints 1 source | * destination
-                    AddressEndpointWithLocation sourceEp = RendererPolicyUtil.lookupEndpoint(rendererEndpoint, configuration.getEndpoints().getAddressEndpointWithLocation());
-                    //resolve sgt
-                    final Sgt sourceSgt = epPolicyCache.lookupValue(new EpPolicyTemplateCacheKey(sourceEp));
-                    for (PeerEndpointWithPolicy peerEndpoint : rendererEndpoint.getPeerEndpointWithPolicy()) {
-                        AddressEndpointWithLocation destinationEp = RendererPolicyUtil.lookupEndpoint(peerEndpoint, configuration.getEndpoints().getAddressEndpointWithLocation());
-                        //resolve sgt
-                        final Sgt destinationSgt = epPolicyCache.lookupValue(new EpPolicyTemplateCacheKey(destinationEp));
-                        // invoke policy manager
-                    }
-                }
+            if (dataAfter != null && dataBefore == null) {
+                policyManager.syncPolicy(dataAfter.getConfiguration(), null);
+            }
+            else if (dataAfter == null && dataBefore != null) {
+                policyManager.syncPolicy(null, dataBefore.getConfiguration());
+            }
+            else if (dataAfter != null) {
+                policyManager.syncPolicy(dataAfter.getConfiguration(), dataBefore.getConfiguration());
             }
         }
     }
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/NodeManager.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/NodeManager.java
new file mode 100644 (file)
index 0000000..9b47ca2
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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.renderer.ios_xe_provider.impl.manager;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.MountPoint;
+import org.opendaylight.controller.md.sal.binding.api.MountPointService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.NodeWriter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class NodeManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NodeManager.class);
+    private static Map<InstanceIdentifier, DataBroker> netconfNodeCache = new HashMap<>();
+    private final DataBroker dataBroker;
+    private MountPointService mountService;
+
+    public NodeManager(final DataBroker dataBroker, BindingAwareBroker.ProviderContext session) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+        mountService = Preconditions.checkNotNull(session.getSALService(MountPointService.class));
+    }
+
+    public static DataBroker getDataBrokerFromCache(InstanceIdentifier iid) {
+        return netconfNodeCache.get(iid); // TODO read from DS
+    }
+
+    public void syncNodes(List<Topology> dataAfter, List<Topology> dataBefore) {
+        if (dataAfter != null && !dataAfter.isEmpty()) {
+            updateNodes(dataAfter);
+        }
+    }
+
+    private void updateNodes(List<Topology> data) {
+        // WRITE
+        NodeWriter nodeWriter = new NodeWriter();
+        for (Topology topology : data) {
+            if (topology.getNode() == null || topology.getNode().isEmpty()) {
+                continue;
+            }
+            topology.getNode().stream().filter(this::isNetconfDevice).forEach(node -> {
+                DataBroker mountpoint = getNodeMountPoint(topology.getTopologyId(), node);
+                if (mountpoint != null) {
+                    netconfNodeCache.put(getMountpointIid(topology.getTopologyId(), node), mountpoint);
+                    RendererNode rendererNode = remap(topology.getTopologyId(), node);
+                    nodeWriter.write(rendererNode);
+                }
+            });
+        }
+        nodeWriter.commitToDatastore(dataBroker);
+    }
+
+    private DataBroker getNodeMountPoint(TopologyId topologyId, Node node) {
+        NetconfNode netconfNode = node.getAugmentation(NetconfNode.class);
+        if (netconfNode == null) {
+            return null;
+        }
+        InstanceIdentifier mountPointIid = getMountpointIid(topologyId, node);
+        Optional<MountPoint> optionalObject = mountService.getMountPoint(mountPointIid);
+        MountPoint mountPoint;
+        if (optionalObject.isPresent()) {
+            mountPoint = optionalObject.get();
+            if (mountPoint != null) {
+                Optional<DataBroker> optionalDataBroker = mountPoint.getService(DataBroker.class);
+                if (optionalDataBroker.isPresent()) {
+                    return optionalDataBroker.get();
+                } else {
+                    LOG.debug("Cannot obtain data broker from mountpoint {}", mountPoint);
+                }
+            } else {
+                LOG.debug("Cannot obtain mountpoint with IID {}", mountPointIid);
+            }
+        }
+        return null;
+    }
+
+    private InstanceIdentifier getMountpointIid(TopologyId topologyId, Node node) {
+        return InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(topologyId))
+                .child(Node.class, new NodeKey(node.getNodeId())).build();
+    }
+
+    private RendererNode remap(TopologyId topologyId, Node node) {
+        InstanceIdentifier<Node> nodeIid = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(topologyId))
+                .child(Node.class, new NodeKey(node.getNodeId())).build();
+        RendererNodeBuilder rendererNodeBuilder = new RendererNodeBuilder();
+        rendererNodeBuilder.setKey(new RendererNodeKey(nodeIid))
+                .setNodePath(nodeIid);
+        return rendererNodeBuilder.build();
+    }
+
+    private boolean isNetconfDevice(Node node) {
+        NetconfNode netconfAugmentation = node.getAugmentation(NetconfNode.class);
+        if (netconfAugmentation == null) {
+            LOG.debug("Node {} is not a netconf device", node.getNodeId().getValue());
+            return false;
+        }
+        if (netconfAugmentation.getConnectionStatus().equals(NetconfNodeConnectionStatus.ConnectionStatus.Connected)) {
+            LOG.info("Node {} ready", node.getNodeId().getValue());
+            return true;
+        }
+        LOG.info("Node {} not connected yet", node.getNodeId().getValue());
+        return false;
+    }
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImpl.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyManagerImpl.java
new file mode 100644 (file)
index 0000000..0a077b2
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * 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.renderer.ios_xe_provider.impl.manager;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.groupbasedpolicy.api.sf.AllowActionDefinition;
+import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.manager.PolicyManager;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyManagerUtil;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.PolicyWriter;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util.RendererPolicyUtil;
+import org.opendaylight.sfc.provider.api.SfcProviderServiceForwarderAPI;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SffName;
+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.sfp.rev140701.service.function.paths.ServiceFunctionPath;
+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.ClassMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChain;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ServiceChainBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
+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.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.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.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.ServiceIndexBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.Services;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.ServicesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.ServiceTypeChoice;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.service.chain.service.path.config.service.chain.path.mode.service.index.services.service.type.choice.ServiceFunctionForwarderBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.config.service.chain.grouping.IpBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionDefinitionId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.rule.group.with.renderer.endpoint.participation.RuleGroupWithRendererEndpointParticipation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointWithPolicy;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.rule.groups.RuleGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.actions.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.classifiers.Classifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.has.resolved.rules.ResolvedRule;
+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.sxp.database.rev160308.Sgt;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction.In;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.HasDirection.Direction.Out;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.CONSUMER;
+import static org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation.PROVIDER;
+
+public class PolicyManagerImpl implements PolicyManager {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyMapper.class);
+    private final DataBroker dataBroker;
+    private DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache;
+    private final PolicyMapper mapper;
+    private final String policyMapName = "service-chains";
+    private Map<DataBroker, PolicyWriter> perDeviceWriterCache = new HashMap<>();
+
+    public enum ActionCase {ALLOW, CHAIN}
+
+
+    public PolicyManagerImpl(final DataBroker dataBroker,
+                             final DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> epPolicyCache) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+        this.epPolicyCache = Preconditions.checkNotNull(epPolicyCache);
+        mapper = new PolicyMapper(dataBroker);
+    }
+
+    @Override
+    public ListenableFuture<Boolean> syncPolicy(final Configuration dataAfter, final Configuration dataBefore) {
+        // CREATE
+        for (RendererEndpoint rendererEndpoint : dataAfter.getRendererEndpoints().getRendererEndpoint()) {
+            // Get mountpoint
+            if (dataAfter.getEndpoints() == null) {
+                continue;
+            }
+            DataBroker mountpoint = getAbsoluteLocationMountpoint(rendererEndpoint, dataAfter.getEndpoints()
+                    .getAddressEndpointWithLocation());
+            if (mountpoint == null) {
+                continue;
+            }
+            // Initialize appropriate writer
+            PolicyWriter policyWriter;
+            if (perDeviceWriterCache.containsKey(mountpoint)) {
+                policyWriter = perDeviceWriterCache.get(mountpoint);
+            } else {
+                policyWriter = new PolicyWriter(mountpoint);
+                perDeviceWriterCache.put(mountpoint, policyWriter);
+            }
+            // Peer Endpoint
+            for (PeerEndpointWithPolicy peerEndpoint : rendererEndpoint.getPeerEndpointWithPolicy()) {
+                // Sgt Tags
+                final Sgt sourceSgt = findSgtTag(rendererEndpoint, dataAfter.getEndpoints()
+                        .getAddressEndpointWithLocation());
+                final Sgt destinationSgt = findSgtTag(peerEndpoint, dataAfter.getEndpoints()
+                        .getAddressEndpointWithLocation());
+                if (sourceSgt == null || destinationSgt == null) {
+                    continue;
+                }
+                syncPolicyEntities(sourceSgt, destinationSgt, policyWriter, dataAfter, peerEndpoint);
+            }
+        }
+        // Flush
+        perDeviceWriterCache.values().forEach(PolicyWriter::commitToDatastore);
+        perDeviceWriterCache.clear();
+
+        return Futures.immediateFuture(true);
+    }
+
+    private void syncPolicyEntities(final Sgt sourceSgt, final Sgt destinationSgt, PolicyWriter policyWriter,
+                                   final Configuration dataAfter, final PeerEndpointWithPolicy peerEndpoint) {
+        // Class map
+        String classMapName = generateClassMapName(sourceSgt.getValue(), destinationSgt.getValue());
+        Match match = mapper.createSecurityGroupMatch(sourceSgt.getValue(), destinationSgt.getValue());
+        ClassMap classMap = mapper.createClassMap(classMapName, match);
+        policyWriter.write(classMap);
+
+        Map<ActionCase, Action> actionMap = getActionInDirection(dataAfter, peerEndpoint);
+        if (actionMap == null || actionMap.isEmpty()) {
+            return;
+        }
+        // Policy map entry
+        List<Class> policyMapEntries = new ArrayList<>();
+        if (actionMap.containsKey(ActionCase.ALLOW)) {
+            policyMapEntries = resolveAllowAction();
+        }
+        if (actionMap.containsKey(ActionCase.CHAIN)) {
+            policyMapEntries = resolveChainAction(peerEndpoint, sourceSgt, destinationSgt, actionMap, classMapName);
+        }
+        policyWriter.write(policyMapEntries);
+    }
+
+    private Sgt findSgtTag(final AddressEndpointKey endpointKey,
+                            final List<AddressEndpointWithLocation> endpointsWithLocation) {
+        if (endpointKey == null || endpointsWithLocation == null) {
+            return null;
+        }
+        AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpointKey,
+                endpointsWithLocation);
+        return epPolicyCache.lookupValue(new EpPolicyTemplateCacheKey(endpointWithLocation));
+    }
+
+    private List<Class> resolveChainAction(final PeerEndpointWithPolicy peerEndpoint, final Sgt sourceSgt,
+                                           final Sgt destinationSgt, final Map<ActionCase, Action> actionMap,
+                                           final String classMapName) {
+        List<Class> entries = new ArrayList<>();
+        final Action action = actionMap.get(ActionCase.CHAIN);
+        ServiceFunctionPath servicePath = PolicyManagerUtil.getServicePath(action.getParameterValue());
+        if (servicePath == null) {
+            return null;
+        }
+        TenantId tenantId = getTenantId(peerEndpoint);
+        if (tenantId == null) {
+            return  null;
+        }
+        RenderedServicePath renderedPath = PolicyManagerUtil.createRenderedPath(servicePath, tenantId);
+        entries.add(mapper.createPolicyEntry(classMapName, renderedPath, ActionCase.CHAIN));
+        if (servicePath.isSymmetric()) {
+            // symmetric path is in opposite direction. Roles of renderer and peer endpoint will invert
+            RenderedServicePath symmetricPath = PolicyManagerUtil
+                    .createSymmetricRenderedPath(servicePath, renderedPath, tenantId);
+            String oppositeClassMapName = generateClassMapName(destinationSgt.getValue(), sourceSgt.getValue());
+            entries.add(mapper.createPolicyEntry(oppositeClassMapName, symmetricPath, ActionCase.CHAIN));
+        }
+        return entries;
+    }
+
+    private List<Class> resolveAllowAction() {
+        List<Class> entries = new ArrayList<>();
+        entries.add(mapper.createPolicyEntry(policyMapName, null, ActionCase.ALLOW));
+        return entries;
+    }
+
+    private DataBroker getAbsoluteLocationMountpoint(final RendererEndpoint endpoint,
+                                                     final List<AddressEndpointWithLocation> endpointsWithLocation) {
+        if (endpoint == null || endpointsWithLocation == null) {
+            return null;
+        }
+        AddressEndpointWithLocation endpointWithLocation = RendererPolicyUtil.lookupEndpoint(endpoint,
+                endpointsWithLocation);
+        final AbsoluteLocation absoluteLocation = endpointWithLocation.getAbsoluteLocation();
+        final LocationType locationType = absoluteLocation.getLocationType();
+        ExternalLocationCase location = (ExternalLocationCase) locationType;
+        if (location == null) {
+            LOG.warn("Endpoint {} does not contain info about external location",
+                    endpointWithLocation.getKey().toString());
+            return null;
+        }
+        InstanceIdentifier mountPointId = location.getExternalNodeMountPoint();
+        return NodeManager.getDataBrokerFromCache(mountPointId);
+    }
+
+    private String generateClassMapName(Integer sourceTag, Integer destinationTag) {
+        return "srcTag" + sourceTag + "_dstTag" + destinationTag;
+    }
+
+    private Map<ActionCase, Action> getActionInDirection(Configuration data, PeerEndpointWithPolicy peer) {
+        List<ResolvedRule> rulesInDirection = new ArrayList<>();
+        // Find all rules in desired direction
+        for (RuleGroupWithRendererEndpointParticipation ruleGroupKey :
+                peer.getRuleGroupWithRendererEndpointParticipation()) {
+            EndpointPolicyParticipation participation = ruleGroupKey.getRendererEndpointParticipation();
+            RuleGroup ruleGroup = findRuleGroup(data, ruleGroupKey);
+            if (ruleGroup == null || ruleGroup.getResolvedRule() == null) {
+                continue;
+            }
+
+            for (ResolvedRule resolvedRule : ruleGroup.getResolvedRule()) {
+                if (resolvedRule == null) {
+                    continue;
+                }
+                if (resolvedRule.getClassifier() == null || resolvedRule.getAction() == null) {
+                    continue;
+                }
+                // TODO only first Classifier used
+                Classifier classifier = resolvedRule.getClassifier().get(0);
+                HasDirection.Direction direction = classifier.getDirection();
+                if ((participation.equals(PROVIDER) && direction.equals(Out)) ||
+                        (participation.equals(CONSUMER) && direction.equals(In))) {
+                    rulesInDirection.add(resolvedRule);
+                }
+            }
+        }
+        if (rulesInDirection.isEmpty()) {
+            return null; // TODO define drop?
+        }
+        // TODO use only first rule with ActionDefinitionID for now
+        Map<ActionCase, Action> result = new HashMap<>();
+        for (ResolvedRule resolvedRule : rulesInDirection) {
+            // TODO only first action used for now
+            Action action = resolvedRule.getAction().get(0);
+            if (action.getActionDefinitionId() != null) {
+                ActionDefinitionId actionDefinitionId = action.getActionDefinitionId();
+                if (actionDefinitionId.equals(AllowActionDefinition.ID)) {
+                    result.put(ActionCase.ALLOW, action);
+                    return result;
+                } else if (actionDefinitionId.equals(ChainActionDefinition.ID)) {
+                    result.put(ActionCase.CHAIN, action);
+                    return result;
+                }
+            }
+        }
+        return null;
+    }
+
+    private RuleGroup findRuleGroup(final Configuration data,
+                                    final RuleGroupWithRendererEndpointParticipation ruleGroupWithParticipation) {
+        final TenantId tenantId = ruleGroupWithParticipation.getTenantId();
+        final ContractId contractId = ruleGroupWithParticipation.getContractId();
+        final SubjectName subjectName = ruleGroupWithParticipation.getSubjectName();
+        for (RuleGroup ruleGroup : data.getRuleGroups().getRuleGroup()) {
+            if (!ruleGroup.getTenantId().equals(tenantId))
+                continue;
+            if (!ruleGroup.getContractId().equals(contractId)) {
+                continue;
+            }
+            if (ruleGroup.getSubjectName().equals(subjectName)) {
+                return ruleGroup;
+            }
+        }
+        return null;
+    }
+
+    private TenantId getTenantId(PeerEndpointWithPolicy peer) {
+        for (RuleGroupWithRendererEndpointParticipation ruleGroup :
+                peer.getRuleGroupWithRendererEndpointParticipation()) {
+            if (ruleGroup.getTenantId() != null) {
+                return ruleGroup.getTenantId();
+            }
+        }
+        return null;
+    }
+
+
+    private void resolveFirstSffOnClassifier(final Ipv4Address nodeIpAddress,
+                                             final Set<RenderedServicePath> firstHops) {
+        // Local forwarder
+        LocalBuilder localSffBuilder = new LocalBuilder();
+        localSffBuilder.setIp(new IpBuilder().setAddress(nodeIpAddress).build());
+
+        // TODO add sff to writer
+
+        for (RenderedServicePath renderedPath : firstHops) {
+            // Remote forwarder
+            RenderedServicePathHop firstRenderedPathHop = renderedPath.getRenderedServicePathHop().get(0);
+            SffName sffName = firstRenderedPathHop.getServiceFunctionForwarder();
+
+            // Remap sff and its management ip address
+            org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.rev140701.service.function.forwarders.ServiceFunctionForwarder serviceFunctionForwarder =
+                    SfcProviderServiceForwarderAPI.readServiceFunctionForwarder(sffName);
+            String sffMgmtIpAddress = serviceFunctionForwarder.getIpMgmtAddress().getIpv4Address().getValue();
+
+            ServiceFfNameBuilder remoteSffBuilder = new ServiceFfNameBuilder();
+            remoteSffBuilder.setName(sffName.getValue())
+                    .setKey(new ServiceFfNameKey(sffName.getValue()))
+                    .setIp(new IpBuilder().setAddress(new Ipv4Address(sffMgmtIpAddress)).build());
+            // TODO add sff to writer
+
+            // Service chain
+            List<Services> services = new ArrayList<>();
+            ServiceTypeChoice serviceTypeChoice = sffTypeChoice(sffName.getValue());
+            ServicesBuilder servicesBuilder = new ServicesBuilder();
+            servicesBuilder.setServiceIndexId(renderedPath.getStartingIndex())
+                    .setServiceTypeChoice(serviceTypeChoice);
+            List<ServicePath> servicePaths = new ArrayList<>();
+            ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
+            servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
+                    .setServicePathId(renderedPath.getPathId())
+                    .setConfigServiceChainPathMode(new ConfigServiceChainPathModeBuilder()
+                            .setServiceIndex(new ServiceIndexBuilder()
+                                    .setServices(services).build()).build());
+            servicePaths.add(servicePathBuilder.build());
+            ServiceChainBuilder chainBuilder = new ServiceChainBuilder();
+            chainBuilder.setServicePath(servicePaths);
+            ServiceChain serviceChain = chainBuilder.build();
+            // TODO add service-chain to writer
+        }
+    }
+
+    private ServiceTypeChoice sffTypeChoice(String forwarderName) {
+        ServiceFunctionForwarderBuilder sffBuilder = new ServiceFunctionForwarderBuilder();
+        sffBuilder.setServiceFunctionForwarder(forwarderName);
+        return sffBuilder.build();
+    }
+
+    @Override
+    public void close() {
+        //NOOP
+    }
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyMapper.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/manager/PolicyMapper.java
new file mode 100644 (file)
index 0000000..917d9d0
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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.renderer.ios_xe_provider.impl.manager;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.ios.rev160308.ClassNameType;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308.PolicyActionType;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.SecurityGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Destination;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.Source;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._class.map.match.grouping.security.group.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.Type;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.TypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.PolicyMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.Match;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native._class.map.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.ClassKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionList;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.ActionListKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.ForwardCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.ForwardBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePath;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathBuilder;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.action.list.action.param.forward._case.forward.ServicePathKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl.ActionCase.CHAIN;
+
+class PolicyMapper {
+
+    private final DataBroker dataBroker;
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyMapper.class);
+
+    PolicyMapper(final DataBroker dataBroker) {
+        this.dataBroker = Preconditions.checkNotNull(dataBroker);
+    }
+
+    Match createSecurityGroupMatch(int sourceTag, int destinationTag) {
+        MatchBuilder matchBuilder = new MatchBuilder();
+        SecurityGroupBuilder sgBuilder = new SecurityGroupBuilder();
+        Source source = new SourceBuilder().setTag(sourceTag).build();
+        Destination destination = new DestinationBuilder().setTag(destinationTag).build();
+        sgBuilder.setSource(source)
+                .setDestination(destination);
+        return matchBuilder.setSecurityGroup(sgBuilder.build()).build();
+    }
+
+    ClassMap createClassMap(final String classMapName, Match match) {
+        ClassMapBuilder cmBuilder = new ClassMapBuilder();
+        cmBuilder.setName(classMapName)
+                .setKey(new ClassMapKey(classMapName))
+                .setMatch(match)
+                .setPrematch(ClassMap.Prematch.MatchAll);
+        return cmBuilder.build();
+    }
+
+    Class createPolicyEntry(String policyClassName, RenderedServicePath renderedPath,
+                            PolicyManagerImpl.ActionCase actionCase) {
+        // Forward Case
+        ForwardCaseBuilder forwardCaseBuilder = new ForwardCaseBuilder();
+        if (actionCase.equals(CHAIN) && renderedPath != null) {
+            // Chain Action
+            ForwardBuilder forwardBuilder = new ForwardBuilder();
+            List<ServicePath> servicePaths = new ArrayList<>();
+            ServicePathBuilder servicePathBuilder = new ServicePathBuilder();
+            servicePathBuilder.setKey(new ServicePathKey(renderedPath.getPathId()))
+                    .setServicePathId(renderedPath.getPathId())
+                    .setServiceIndex(renderedPath.getStartingIndex());
+            servicePaths.add(servicePathBuilder.build());
+            forwardBuilder.setServicePath(servicePaths);
+            forwardCaseBuilder.setForward(forwardBuilder.build());
+        }
+        // Create Action List
+        List<ActionList> actionList = new ArrayList<>();
+        ActionListBuilder actionListBuilder = new ActionListBuilder();
+        actionListBuilder.setKey(new ActionListKey(PolicyActionType.Forward))
+                .setActionType(PolicyActionType.Forward)
+                .setActionParam(forwardCaseBuilder.build());
+        actionList.add(actionListBuilder.build());
+        // Build class entry
+        ClassBuilder policyClassBuilder = new ClassBuilder();
+        policyClassBuilder.setName(new ClassNameType(policyClassName))
+                .setKey(new ClassKey(new ClassNameType(policyClassName)))
+                .setActionList(actionList);
+        return policyClassBuilder.build();
+    }
+
+    public Type getServicePolicyType(String name) {
+        TypeBuilder typeBuilder = new TypeBuilder();
+        org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder serviceChainBuilder =
+                new org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChainBuilder();
+        serviceChainBuilder.setName(name)
+                .setDirection(org.opendaylight.yang.gen.v1.urn.ios.rev160308._interface.common.grouping.service.policy.type.ServiceChain.Direction.Input);
+        typeBuilder.setServiceChain(serviceChainBuilder.build());
+        return typeBuilder.build();
+    }
+
+    PolicyMap policyMap(String policyMapName) {
+        PolicyMapBuilder pmBuilder = new PolicyMapBuilder();
+        pmBuilder.setName(policyMapName)
+                .setKey(new PolicyMapKey(policyMapName))
+                .setType(null);
+        return pmBuilder.build();
+    }
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/NodeWriter.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/NodeWriter.java
new file mode 100644 (file)
index 0000000..2d4a3f7
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.util;
+
+import com.google.common.util.concurrent.CheckedFuture;
+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.renderer.rev151103.RendererName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class NodeWriter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(NodeWriter.class);
+    private List<RendererNode> rendererNodesCache;
+
+    public NodeWriter() {
+        rendererNodesCache = new ArrayList<>();
+    }
+
+    public void write(RendererNode node) {
+        rendererNodesCache.add(node);
+    }
+
+    public void commitToDatastore(DataBroker dataBroker) {
+        RendererNodes rendererNodes = buildRendererNodes();
+        WriteTransaction wtx = dataBroker.newWriteOnlyTransaction();
+        InstanceIdentifier<RendererNodes> Iid = InstanceIdentifier.builder(Renderers.class)
+                .child(Renderer.class, new RendererKey(new RendererName("ios-xe-renderer"))) // TODO unify renderer name
+                .child(RendererNodes.class)
+                .build();
+        try {
+            wtx.merge(LogicalDatastoreType.OPERATIONAL, Iid, rendererNodes, true);
+            CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+            submitFuture.checkedGet();
+            // Clear cache
+            rendererNodesCache.clear();
+        } catch (TransactionCommitFailedException e) {
+            LOG.error("Write transaction failed to {}", e.getMessage());
+        } catch (Exception e) {
+            LOG.error("Failed to .. {}", e.getMessage());
+        }
+    }
+
+    private RendererNodes buildRendererNodes() {
+        RendererNodesBuilder rendererNodesBuilder = new RendererNodesBuilder();
+        rendererNodesBuilder.setRendererNode(rendererNodesCache);
+        return rendererNodesBuilder.build();
+    }
+
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyManagerUtil.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyManagerUtil.java
new file mode 100644 (file)
index 0000000..85b7737
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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.renderer.ios_xe_provider.impl.util;
+
+import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
+import org.opendaylight.sfc.provider.api.SfcProviderRenderedPathAPI;
+import org.opendaylight.sfc.provider.api.SfcProviderServicePathAPI;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.RspName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.common.rev151017.SfcName;
+import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.rsp.rev140701.CreateRenderedPathInput;
+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.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.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.subject.feature.instance.ParameterValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PolicyManagerUtil {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyManagerUtil.class);
+
+    public static ServiceFunctionPath getServicePath(List<ParameterValue> params) {
+        if (params == null || params.isEmpty()) {
+            LOG.error("Cannot found service path, parameter value is null");
+            return null;
+        }
+        Map<String, Object> paramsMap = new HashMap<>();
+        for (ParameterValue value : params) {
+            if (value.getName() == null)
+                continue;
+            if (value.getIntValue() != null) {
+                paramsMap.put(value.getName().getValue(), value.getIntValue());
+            } else if (value.getStringValue() != null) {
+                paramsMap.put(value.getName().getValue(), value.getStringValue());
+            }
+        }
+        String chainName = null;
+        for (String name : paramsMap.keySet()) {
+            if (name.equals(ChainActionDefinition.SFC_CHAIN_NAME)) {
+                chainName = (String) paramsMap.get(name);
+            }
+        }
+        if (chainName == null) {
+            LOG.error("Cannot found service path, chain name is null");
+            return null;
+        }
+        ServiceFunctionPath serviceFunctionPath = findServiceFunctionPath(new SfcName(chainName));
+        if (serviceFunctionPath == null) {
+            LOG.error("Service function path not found for name {}", chainName);
+            return null;
+        }
+        return serviceFunctionPath;
+    }
+
+    public static RenderedServicePath createRenderedPath(ServiceFunctionPath sfp, TenantId tenantId) {
+        RenderedServicePath renderedServicePath;
+        // Try to read existing RSP
+        RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp");
+        renderedServicePath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+        if (renderedServicePath != null) {
+            return renderedServicePath;
+        }
+        LOG.info("Rendered service path with name {} not found, creating a new one ..", rspName.getValue());
+        CreateRenderedPathInput input = new CreateRenderedPathInputBuilder()
+                .setParentServiceFunctionPath(sfp.getName().getValue())
+                .setName(rspName.getValue())
+                .setSymmetric(sfp.isSymmetric())
+                .build();
+        renderedServicePath = SfcProviderRenderedPathAPI.createRenderedServicePathAndState(sfp, input);
+        LOG.info("Rendered service path {} created", rspName.getValue());
+        return renderedServicePath;
+    }
+
+    private static ServiceFunctionPath findServiceFunctionPath(SfcName chainName) {
+        ServiceFunctionPaths allPaths = SfcProviderServicePathAPI.readAllServiceFunctionPaths();
+        for (ServiceFunctionPath serviceFunctionPath : allPaths.getServiceFunctionPath()) {
+            if (serviceFunctionPath.getServiceChainName().equals(chainName)) {
+                return serviceFunctionPath;
+            }
+        }
+        return null;
+    }
+
+    public static RenderedServicePath createSymmetricRenderedPath(ServiceFunctionPath sfp, RenderedServicePath rsp,
+                                                                  TenantId tenantId) {
+        RenderedServicePath reversedRenderedPath;
+        // Try to read existing RSP
+        RspName rspName = new RspName(sfp.getName().getValue() + tenantId.getValue() + "-gbp-rsp-Reverse");
+        reversedRenderedPath = SfcProviderRenderedPathAPI.readRenderedServicePath(rspName);
+        if (reversedRenderedPath != null) {
+            return reversedRenderedPath;
+        }
+        LOG.info("Reversed rendered service path with name {} not found, creating a new one ..", rspName.getValue());
+        reversedRenderedPath = SfcProviderRenderedPathAPI.createSymmetricRenderedServicePathAndState(rsp);
+        LOG.info("Rendered service path {} created", rspName.getValue());
+        return reversedRenderedPath;
+    }
+
+}
diff --git a/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyWriter.java b/renderers/ios-xe/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ios_xe_provider/impl/util/PolicyWriter.java
new file mode 100644 (file)
index 0000000..f7827a4
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.renderer.ios_xe_provider.impl.util;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+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.ios.rev160308.Native;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMap;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.ClassMapKey;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map.Class;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PolicyWriter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PolicyWriter.class);
+
+    private final DataBroker mountpoint;
+    // Local cache
+    private List<ClassMap> classMapEntries;
+    private List<Class> policyMapEntries;
+
+    public PolicyWriter(final DataBroker dataBroker) {
+        mountpoint = Preconditions.checkNotNull(dataBroker);
+        classMapEntries = new ArrayList<>();
+        policyMapEntries = new ArrayList<>();
+    }
+
+    public void write(ClassMap classMap) {
+        classMapEntries.add(classMap);
+    }
+
+    public void write(List<Class> policyMapEntries) {
+        this.policyMapEntries.addAll(policyMapEntries);
+    }
+
+    public void commitToDatastore() {
+        // create and write service-policy
+        // create and write policy-map with policyMapEntries
+        // create and write class-maps
+
+        WriteTransaction wtx = mountpoint.newWriteOnlyTransaction();
+        // Class maps
+        for (ClassMap entry : classMapEntries) {
+            InstanceIdentifier<ClassMap> iid = classMapInstanceIdentifier(entry);
+            try {
+                wtx.merge(LogicalDatastoreType.CONFIGURATION, iid, entry, true);
+                CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wtx.submit();
+                submitFuture.checkedGet();
+                // Clear cache
+                classMapEntries.clear();
+            } catch (TransactionCommitFailedException e) {
+                LOG.error("Write transaction failed to {}", e.getMessage());
+            } catch (Exception e) {
+                LOG.error("Failed to .. {}", e.getMessage());
+            }
+        }
+    }
+
+    private InstanceIdentifier<ClassMap> classMapInstanceIdentifier(ClassMap classMap) {
+        return InstanceIdentifier.builder(Native.class)
+                .child(ClassMap.class, new ClassMapKey(classMap.getName())).build();
+    }
+}
@@ -1,5 +1,5 @@
-package org.opendaylight.yang.gen.v1.urn.ios.rev160516._native.mls.qos;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160516._native.mls.qos.Map.PolicedDscp;
+package org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.mls.qos;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.mls.qos.Map.PolicedDscp;
 
 
 /**
@@ -1,5 +1,5 @@
-package org.opendaylight.yang.gen.v1.urn.ios.rev160516._native.policy.map._class.pm.policy.monitor.metric.rtp;
-import org.opendaylight.yang.gen.v1.urn.ios.rev160516._native.policy.map._class.pm.policy.monitor.metric.rtp.ClockRate.Number;
+package org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.pm.policy.monitor.metric.rtp;
+import org.opendaylight.yang.gen.v1.urn.ios.rev160308._native.policy.map._class.pm.policy.monitor.metric.rtp.ClockRate.Number;
 
 
 /**
index 5d73d609b538758eb290550b33e8f6f937ec6a57..5c51b7c16364a8266f189db1fb60282f19823094 100644 (file)
@@ -21,7 +21,7 @@ module ned {
         "This file was adapted to be parsed by yangtools for groupbasedpolicy project purpose";
 
     revision
-        2016-05-16;
+        2016-03-8;
 
 /// ========================================================================
 /// typedefs
@@ -1758,6 +1758,173 @@ module ned {
         }
     }
 
+    grouping interface-atm-grouping {
+        // Removed body
+    }
+
+    grouping interface-cellular-grouping {
+        //interface * / dialer
+        container dialer {
+            leaf in-band {
+                type empty;
+            }
+            leaf idle-timeout {
+                type uint32;
+            }
+            leaf string {
+                type string;
+            }
+            leaf watch-group {
+                type uint32;
+            }
+        }
+        //interface * / async
+        container async {
+            leaf mode {
+                type enumeration {
+                    enum interactive;
+                }
+            }
+        }
+    }
+
+    grouping interface-common-grouping {
+        // interface * / service-policy
+        container service-policy {
+            tailf:info "Configure QoS Service Policy";
+            description "Configure QoS Service Policy";
+            leaf history {
+                tailf:cli-full-command;
+                tailf:info "Keep history of QoS metrics";
+                   description "Keep history of QoS metrics";
+                type empty;
+            }
+            leaf "input" {
+                tailf:cli-full-command;
+                tailf:info "Assign policy-map to the input of an interface";
+                description "Assign policy-map to the input of an interface";
+                type string {
+                    tailf:info "WORD;;policy-map name";
+                }
+                tailf:non-strict-leafref {
+                    path "/ios:native/policy-map/name";
+                }
+            }
+            leaf "output" {
+                tailf:cli-full-command;
+                tailf:info "Assign policy-map to the output of an interface";
+                description "Assign policy-map to the output of an interface";
+                type string {
+                    tailf:info "WORD;;policy-map name";
+                }
+                tailf:non-strict-leafref {
+                    path "/ios:native/policy-map/name";
+                }
+            }
+            container "type" {
+                tailf:info "Configure CPL Service Policy";
+                description "Configure CPL Service Policy";
+                container performance-monitor {
+                    tailf:info "Configure media monitor service-policy type";
+                    description "Configure media monitor service-policy type";
+                    tailf:cli-sequence-commands;
+                    tailf:cli-compact-syntax;
+                    leaf direction {
+                        tailf:cli-drop-node-name;
+                        type enumeration {
+                            enum "input" {
+                                tailf:info "Assign policy-map to the input of an interfcae";
+                            }
+                            enum "output" {
+                                tailf:info "Assign policy-map to the output of an interfcae";
+                            }
+                        }
+                    }
+                    leaf name {
+                        tailf:cli-drop-node-name;
+                        type string {
+                            tailf:info "WORD;;policy-map name";
+                        }
+                        tailf:non-strict-leafref {
+                            path "/ios:native/policy-map/name";
+                        }
+                    }
+                }
+                // interface * / service-policy type * / service-chain
+                container service-chain {
+                    tailf:info "Configure Service-chain Service Policy";
+                    description "Configure Service-chain Service Policy";
+                    tailf:cli-sequence-commands;
+                    tailf:cli-compact-syntax;
+                    leaf direction {
+                        tailf:cli-drop-node-name;
+                        type enumeration {
+                            enum "input" {
+                                tailf:info "Assign policy-map to the input of an interfcae";
+                            }
+                            enum "output" {
+                                tailf:info "Assign policy-map to the output of an interfcae";
+                            }
+                        }
+                    }
+                    leaf name {
+                        tailf:cli-drop-node-name;
+                        type string {
+                            tailf:info "WORD;;policy-map name";
+                        }
+                        tailf:non-strict-leafref {
+                            path "/ios:native/policy-map/name";
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    grouping interface-ethernet-grouping {
+        // Removed body
+    }
+
+    grouping interface-grouping {
+        // Removed body
+    }
+
+    grouping interface-overlay-grouping {
+        // Removed body
+    }
+
+    grouping interface-pointtopoint-grouping {
+        // Removed body
+    }
+
+    grouping interface-pseudowire-grouping {
+        // Removed body
+    }
+
+    grouping interface-switch-grouping {
+        // Removed body
+    }
+
+    grouping interface-tunnel-grouping {
+        // Removed body
+    }
+
+    grouping interface-zone-member-grouping {
+        // interface * / zone-member
+        container zone-member {
+            tailf:info "Apply zone name";
+            description "Apply zone name";
+            leaf security {
+                tailf:info "Security zone";
+                description "Security zone";
+                type string;
+                tailf:non-strict-leafref {
+                    path "/ios:native/zone/security/id";
+                }
+            }
+        }
+    }
+
     grouping police-action-drop-grouping {
         leaf drop {
             tailf:info "drop packet";
@@ -2492,6 +2659,10 @@ module ned {
         }
     }
 
+    grouping pseudowire-grouping {
+        // Removed body
+    }
+
     grouping random-detect-grouping {
         leaf min-threshold {
             tailf:cli-drop-node-name;
@@ -2518,6 +2689,7 @@ module ned {
         }
     }
 
+
 /// ========================================================================
 /// native
 /// ========================================================================
@@ -2543,6 +2715,766 @@ module ned {
             }
         }
 
+/// ========================================================================
+/// interface
+/// ========================================================================
+
+    container interface {
+        tailf:info "Configure interfaces";
+        description "Configure interfaces";
+        tailf:cli-diff-dependency "/ios:native/vrf";
+        tailf:cli-explicit-exit;
+
+        // interface AppNav-Compress
+        list AppNav-Compress {
+            tailf:info "Service-Context Virtual Interface Compress";
+            description "Service-Context Virtual Interface Compress";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-suppress-key-abbreviation;
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-1000>;;AppNav-Compress interface number";
+                    range "1..1000";
+                }
+            }
+            uses interface-common-grouping;
+        }
+        // interface AppNav-UnCompress
+        list AppNav-UnCompress {
+            tailf:info "Service-Context Virtual Interface UnCompress";
+            description "Service-Context Virtual Interface UnCompress";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-suppress-key-abbreviation;
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-1000>;;AppNav-UnCompress interface number";
+                    range "1..1000";
+                }
+            }
+            uses interface-common-grouping;
+        }
+
+        // interface ATM #
+        list ATM {
+            tailf:info "ATM interface";
+            description "ATM interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-suppress-key-abbreviation;
+            key name;
+            leaf name {
+                type string {
+                    tailf:info "<slot>/<subslot>/<port>;;ATM interface number";
+                    pattern "([0-9]/){2}([0-9]|(ima[0-9]))(:[0-9])?";
+                }
+            }
+            uses interface-atm-grouping;
+        }
+
+        // subinterface ATM #.#
+        container ATM-subinterface {
+            tailf:cli-drop-node-name;
+            list ATM {
+                tailf:cli-allow-join-with-key {
+                    tailf:cli-display-joined;
+                }
+                tailf:cli-mode-name "config-subif";
+                tailf:cli-suppress-key-abbreviation;
+                key name;
+                leaf name {
+                    type string {
+                        pattern "([0-9]/){2}[0-9]\.([0-9]/){3}[0-9]";
+                    }
+                }
+                uses interface-atm-grouping;
+            }
+        }
+
+        // interface ATM-ACR #
+        list ATM-ACR {
+            tailf:info "ATM-ACR interface";
+            description "ATM-ACR interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-suppress-key-abbreviation;
+            key name;
+            leaf name {
+                type string {
+                    tailf:info "<slot>/<subslot>/<port>;;ATM-ACR interface number";
+                    pattern "[0-9]";
+                }
+            }
+            uses interface-atm-grouping;
+        }
+
+        // subinterface ATM-ACR #.#
+        container ATM-ACRsubinterface {
+            tailf:cli-drop-node-name;
+            list ATM-ACR {
+                tailf:cli-allow-join-with-key {
+                    tailf:cli-display-joined;
+                }
+                tailf:cli-mode-name "config-subif";
+                tailf:cli-suppress-key-abbreviation;
+                key name;
+                leaf name {
+                    type string {
+                        pattern "[0-9]\.([0-9]/){3}[0-9]";
+                    }
+                }
+                uses interface-atm-grouping;
+            }
+        }
+        // interface BDI
+        list BDI {
+            tailf:info "Bridge-Domain interface";
+            description "Bridge-Domain interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            key name;
+            leaf name {
+                type string {
+                    // pattern "([0-9])+/([0-9])+(/([0-9])+)?";
+                    tailf:info "<1-16000>;;BDI interface number";
+                }
+            }
+            uses interface-common-grouping;
+        }
+
+        // interface CEM #
+        list CEM {
+            tailf:info "Circuit Emulation interface";
+            description "Circuit Emulation interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-suppress-key-abbreviation;
+            key name;
+            leaf name {
+                type string {
+                    tailf:info "<slot>/<port>;;CEM interface number";
+                    pattern "([0-9]/){2}[0-9]";
+                }
+            }
+            uses interface-atm-grouping;
+        }
+
+        // interface CEM-ACR #
+        list CEM-ACR {
+            tailf:info "Circuit Emulation interface";
+            description "Circuit Emulation interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-suppress-key-abbreviation;
+            key name;
+            leaf name {
+                type uint8 {
+                    tailf:info "<0-255>;;CEM-ACR interface number";
+                    range "0..255";
+                }
+            }
+            uses interface-atm-grouping;
+        }
+
+        // interface Embedded-Service-Engine
+        list Embedded-Service-Engine {
+            tailf:info "cisco embedded service engine module";
+            description "cisco embedded service engine module";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            // tailf:cli-full-command;
+            key name;
+            leaf name {
+                type string {
+                    tailf:info "<0-2>/<0-0>;;Embedded-Service-Engine interface number";
+                }
+            }
+            uses interface-common-grouping;
+        }
+
+        // interface FastEthernet
+        list FastEthernet {
+            tailf:info "FastEthernet IEEE 802.3";
+            description "FastEthernet IEEE 802.3";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+                // tailf:cli-full-command;
+            key name;
+            leaf name {
+                type string {
+                    //pattern "([0-9])+(/([0-9])+)*";
+                    tailf:info "<0-66>/<0-128>;;FastEthernet interface number";
+                }
+            }
+            uses interface-ethernet-grouping;
+            uses interface-common-grouping;
+            uses interface-zone-member-grouping;
+            uses interface-switch-grouping; //CATALYST
+        }
+
+        // interface GigabitEthernet
+        list GigabitEthernet {
+            tailf:info "GigabitEthernet IEEE 802.3z";
+            description "GigabitEthernet IEEE 802.3z";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+                // tailf:cli-full-command;
+            key name;
+            leaf name {
+                type string {
+                    //pattern "([0-9])+(/([0-9])+)*";
+                    tailf:info "<0-66>/<0-128>;;"+
+                        "GigabitEthernet interface number";
+                }
+            }
+            leaf media-type {
+                tailf:info "Media type";
+                description "Media type";
+                type enumeration {
+                    enum auto-select {
+                        tailf:info "Use whichever connector is attached";
+                    }
+                    enum rj45 {
+                        tailf:info "Copper";
+                    }
+                    enum sfp {
+                        tailf:info "Fiber";
+                    }
+                }
+            }
+            leaf port-type {
+                //FIXME: tailf:info
+                //FIXME: 3600 only?
+                type enumeration {
+                    enum nni;
+                }
+            }
+            uses interface-ethernet-grouping;
+            uses interface-common-grouping;
+            uses interface-zone-member-grouping;
+            uses interface-switch-grouping; //CATALYST
+        }
+
+        // interface TenGigabitEthernet
+        list TenGigabitEthernet {
+            tailf:info "Ten Gigabit Ethernet";
+            description "Ten Gigabit Ethernet";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+                // tailf:cli-full-command;
+            key name;
+            leaf name {
+                type string {
+                    //pattern "([0-9])+(/([0-9])+)*";
+                    tailf:info "<0-66>/<0-128>;;"+
+                        "TenGigabitEthernet interface number";
+                }
+            }
+            leaf media-type {
+                tailf:info "Media type";
+                description "Media type";
+                type enumeration {
+                    enum auto-select {
+                        tailf:info "Use whichever connector is attached";
+                    }
+                    enum rj45 {
+                        tailf:info "Copper";
+                    }
+                        enum sfp {
+                        tailf:info "Fiber";
+                    }
+                }
+            }
+            leaf port-type {
+                //FIXME: tailf:info
+                //FIXME: 3600 only?
+                type enumeration {
+                    enum nni;
+                }
+            }
+            uses interface-ethernet-grouping;
+            uses interface-common-grouping;
+            uses interface-zone-member-grouping;
+            uses interface-switch-grouping; //CATALYST
+        }
+
+        // interface Loopback
+        list Loopback {
+            // pvh hide Loopback interfaces
+            //    tailf:hidden full;
+            tailf:info "Loopback interface";
+            description "Loopback interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+                // tailf:cli-full-command;
+            key name;
+            leaf name {
+                type string {
+                    // pattern "([0-9])+/([0-9])+(/([0-9])+)?";
+                    tailf:info "<0-2147483647>;;Loopback interface number";
+                }
+            }
+            uses interface-common-grouping;
+        }
+
+        list nve {
+            tailf:info "Network virtualization endpoint interface";
+            description "Network virtualization endpoint interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-4096>;;nve interface number";
+                    range "1..4096";
+                }
+            }
+
+            container source-interface {
+                tailf:info "Specify source interface for NVE";
+                description "Specify source interface for NVE";
+                // FIXME: tailf:cli-diff-dependency "/ios:native/interface";
+                uses interface-grouping;
+            }
+            container member {
+                tailf:cli-incomplete-command;
+                tailf:cli-sequence-commands;
+                list vni {
+                    tailf:info "Configure VNI information";
+                    description "Configure VNI information";
+                    tailf:cli-sequence-commands;
+                    tailf:cli-compact-syntax;
+
+                    key vni-range;
+                    leaf vni-range {
+                        type string {
+                            tailf:info "WORD;;VNI range or instance between 4096-16777215 example: 6010-6030 or 7115";
+                        }
+                    }
+                    container mcast-group {
+                        tailf:cli-incomplete-command;
+                        tailf:cli-sequence-commands;
+                        leaf multicast-group-min {
+                            tailf:cli-drop-node-name;
+                            tailf:info "Starting Multicast Group IPv4 Address";
+                            description "Starting Multicast Group IPv4 Address";
+                            type inet:ipv4-address {
+                                tailf:info "A.B.C.D;;IP address";
+                            }
+                        }
+                        leaf multicast-group-max {
+                            tailf:cli-drop-node-name;
+                            tailf:info "Ending Multicast Group IPv4 Address";
+                            description "Ending Multicast Group IPv4 Address";
+                            type inet:ipv4-address {
+                                tailf:info "A.B.C.D;;IP address";
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // interface overlay
+        list overlay {
+            tailf:info "Overlay interface";
+            description "Overlay interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<0-512>;;Overlay interface number";
+                    range "0..512";
+                }
+            }
+            uses interface-common-grouping;
+            uses interface-ethernet-grouping;
+            uses interface-overlay-grouping;
+        }
+
+        // interface Port-channel
+        list Port-channel {
+            tailf:info "Ethernet Channel of interfaces";
+            description "Ethernet Channel of interfaces";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+                // tailf:cli-full-command;
+            key name;
+            leaf name {
+                type uint32 {
+                    tailf:info "<1-512>;;Port-channel interface number";
+                    range "1..512";
+                }
+            }
+            leaf pc-speed {
+                tailf:alt-name "speed";
+                tailf:info "Configure speed operation.";
+                description "Configure speed operation.";
+                type enumeration {
+                    enum "10" {
+                        tailf:info "Force 10 Mbps operation";
+                    }
+                    enum "100" {
+                        tailf:info "Force 100 Mbps operation";
+                    }
+                    enum "1000" {
+                        tailf:info "Enable AUTO speed configuration";
+                    }
+                    enum "nonegotiate" {
+                        //FIXME
+                    }
+                    enum "auto" {
+                        tailf:info "Enable AUTO speed configuration";
+                    }
+                }
+            }
+            uses interface-common-grouping;
+            uses interface-switch-grouping; //CATALYST
+            uses interface-ethernet-grouping;
+        }
+
+        // subinterface Port-channel #.#
+        container Port-channel-subinterface {
+            tailf:cli-drop-node-name;
+            list Port-channel {
+                tailf:cli-allow-join-with-key {
+                    tailf:cli-display-joined;
+                }
+                tailf:cli-mode-name "config-subif";
+                tailf:cli-suppress-key-abbreviation;
+                key name;
+                leaf name {
+                    type string;
+                }
+                uses interface-common-grouping;
+                uses interface-switch-grouping; //CATALYST
+                uses interface-ethernet-grouping;
+            }
+        }
+
+        //interface pseudowire
+        list pseudowire {
+            tailf:info "Pseudowire Interface";
+            description "Pseudowire Interface";
+            tailf:cli-mode-name "config-if";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            key name;
+            leaf name {
+                type uint32 {
+                    tailf:info "<1-231072>;;pseudowire interface number";
+                    range "1..231072";
+                }
+            }
+            uses pseudowire-grouping;
+        }
+        //interface SM
+        list "SM" {
+            tailf:info "SM Interface";
+            description "SM Interface";
+            tailf:cli-mode-name "config-if";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            key name;
+            leaf name {
+                type string {
+                    pattern "([0-9])+(/([0-9])+)?";
+                }
+            }
+            uses interface-common-grouping;
+        }
+        //interface Cellular
+        list Cellular {
+            tailf:info "Cellular Interface";
+            description "Cellular Interface";
+            tailf:cli-mode-name "config-if";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            key name;
+            leaf name {
+                type string {
+                    pattern "([0-9])+(/([0-9])+)?";
+                }
+            }
+            uses interface-common-grouping;
+            uses interface-cellular-grouping;
+        }
+
+        // interface Vlan
+        list Vlan {
+            tailf:info "Catalyst Vlans";
+            description "Catalyst Vlans";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-4094>;;Vlan interface number";
+                    range "1..4094";
+                }
+            }
+            uses interface-common-grouping;
+            uses interface-zone-member-grouping;
+        }
+
+        // interface Group-Async
+        list Group-Async {
+            tailf:info "Async Group interface";
+            description "Async Group interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<0-64>;;Group-Async interface number";
+                    range "0..64";
+                }
+            }
+            leaf physical-layer {
+                tailf:info "Configure sync or async physical layer on serial "+
+                    "interface";
+                description "Configure sync or async physical layer on serial "+
+                    "interface";
+                type enumeration {
+                    enum async {
+                        tailf:info "Configure asynchronous physical layer on serial "
+                        +"interface";
+                    }
+                    enum sync {
+                    tailf:info "Configure synchronous physical layer on serial "+
+                        "interface";
+                    }
+                }
+            }
+            uses interface-common-grouping;
+        }
+
+        // interface Multilink
+        list Multilink {
+            tailf:info "Multilink-group interface";
+            description "Multilink-group interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-full-command;
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-65535>;;Multilink interface number";
+                    range "1..65535";
+                }
+            }
+            uses interface-common-grouping;
+            uses interface-pointtopoint-grouping;
+        }
+
+        // interface Serial
+        list Serial {
+            tailf:info "Serial interface";
+            description "Serial interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-full-command;
+            key name;
+            leaf name {
+                type string {
+                    pattern "([0-9])+/([0-9])+/([0-9])+\.([0-9])+/([0-9])+/([0-9])+/([0-9])+:([0-9])";
+                    //FIXME: info + syntax
+                }
+            }
+            uses interface-common-grouping;
+            uses interface-pointtopoint-grouping;
+        }
+
+        // interface Tunnel #
+        list Tunnel {
+            tailf:info "Tunnel interface";
+            description "Tunnel interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-suppress-key-abbreviation;
+            key name;
+            leaf name {
+                type uint32 {
+                    tailf:info "<0-2147483647>;;Tunnel interface number";
+                }
+            }
+            uses interface-common-grouping;
+
+            // interface Tunnel* / qos
+            container qos {
+                tailf:info "Quality of Service related commands";
+                description "Quality of Service related commands";
+                leaf pre-classify {
+                    tailf:info "Enable QOS classification before packets are tunnel "+
+                        "encapsulated";
+                    description "Enable QOS classification before packets are tunnel "+
+                        "encapsulated";
+                    type empty;
+                }
+            }
+
+            // interface Tunnel* / tunnel
+            uses interface-tunnel-grouping;
+        }
+
+        // interface Virtual-Template
+        list Virtual-Template {
+            tailf:info "Virtual Template interface";
+            description "Virtual Template interface";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-full-command;
+            tailf:cli-explicit-exit;
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-4095>;;Virtual-Template interface number";
+                    range "1..4095";
+                }
+            }
+            leaf type {
+                tailf:info "type of the virtual-template";
+                description "type of the virtual-template";
+                tailf:cli-hide-in-submode;
+                type enumeration {
+                    enum ethernet {
+                      tailf:info "Set VT type as ethernet";
+                    }
+                    enum serial {
+                      tailf:info "Set VT type as serial";
+                    }
+                    enum tunnel {
+                      tailf:info "Set VT type as tunnel";
+                    }
+                    enum vpn {
+                      tailf:info "Set VT type as vpn";
+                    }
+                }
+            }
+
+            uses interface-ethernet-grouping;
+            uses interface-common-grouping;
+            uses interface-zone-member-grouping;
+            uses interface-switch-grouping; //CATALYST
+            uses interface-pointtopoint-grouping;
+            // interface Tunnel* / tunnel
+            uses interface-tunnel-grouping;
+        }
+
+        // interface VirtualPortGroup
+        list VirtualPortGroup {
+            tailf:info "Virtual Port Group";
+            description "Virtual Port Group";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-full-command;
+            tailf:cli-explicit-exit;
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info " <0-31>;;VirtualPortGroup interface number";
+                    range "0..31";
+                }
+            }
+            uses interface-switch-grouping; //CATALYST
+            uses interface-ethernet-grouping;
+            uses interface-common-grouping;
+        }
+        // interface vasileft
+        list vasileft {
+            tailf:info "vasileft";
+            description "vasileft";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-full-command;
+            tailf:cli-explicit-exit;
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-2000>;;vasileft interface number";
+                    range "1..2000";
+                }
+            }
+            uses interface-switch-grouping; //CATALYST
+            uses interface-ethernet-grouping;
+            uses interface-common-grouping;
+        }
+
+        // interface vasiright
+        list vasiright {
+            tailf:info "vasiright";
+            description "vasiright";
+            tailf:cli-allow-join-with-key {
+                tailf:cli-display-joined;
+            }
+            tailf:cli-mode-name "config-if";
+            tailf:cli-full-command;
+            tailf:cli-explicit-exit;
+            key name;
+            leaf name {
+                type uint16 {
+                    tailf:info "<1-2000>;;vasiright interface number";
+                    range "1..2000";
+                 }
+            }
+            uses interface-switch-grouping; //CATALYST
+            uses interface-ethernet-grouping;
+            uses interface-common-grouping;
+        }
+    }
+
+
 /// ========================================================================
 /// mls
 /// ========================================================================
index 2bd9d7a763fc60e088ea04eca64cb6ccc019597b..958426efdda733df11e888018eea1b149a521143 100644 (file)
@@ -21,13 +21,10 @@ 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.DataTreeIdentifier;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.api.cache.DSTreeBasedCache;
-import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.cache.EpPolicyTemplateCacheKey;
+import org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
-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.sxp.database.rev160308.Sgt;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 
 /**
@@ -38,10 +35,11 @@ public class RendererConfigurationListenerImplTest {
 
     private static final RendererName RENDERER_NAME = new RendererName("renderer1");
     private final RendererPolicy policy1;
+    private final RendererPolicy policy2;
     @Mock
     private DataBroker dataBroker;
     @Mock
-    private DSTreeBasedCache<EndpointPolicyTemplateBySgt, EpPolicyTemplateCacheKey, Sgt> cache;
+    private PolicyManagerImpl policyManager;
     @Mock
     private ListenerRegistration<RendererConfigurationListenerImpl> listenerRegistration;
     @Mock
@@ -53,6 +51,7 @@ public class RendererConfigurationListenerImplTest {
 
     public RendererConfigurationListenerImplTest() {
         policy1 = new RendererPolicyBuilder().build();
+        policy2 = new RendererPolicyBuilder().build();
     }
 
     @Before
@@ -61,7 +60,7 @@ public class RendererConfigurationListenerImplTest {
                 Matchers.<DataTreeIdentifier<RendererPolicy>>any(),
                 Matchers.<RendererConfigurationListenerImpl>any()))
                 .thenReturn(listenerRegistration);
-        listener = new RendererConfigurationListenerImpl(dataBroker, RENDERER_NAME, cache);
+        listener = new RendererConfigurationListenerImpl(dataBroker, RENDERER_NAME, policyManager);
     }
 
     @After
@@ -72,6 +71,7 @@ public class RendererConfigurationListenerImplTest {
     @Test
     public void testOnDataTreeChanged_add() throws Exception {
         Mockito.when(rootNode.getDataAfter()).thenReturn(policy1);
+        Mockito.when(rootNode.getDataBefore()).thenReturn(policy2);
         Mockito.when(rootNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
         Mockito.when(dataTreeModification.getRootNode()).thenReturn(rootNode);
 
diff --git a/renderers/ios-xe/src/test/resources/log4j.xml b/renderers/ios-xe/src/test/resources/log4j.xml
new file mode 100644 (file)
index 0000000..78ad669
--- /dev/null
@@ -0,0 +1,34 @@
+<?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.renderer.ios_xe_provider" additivity="false">\r
+        <level value="DEBUG"/>\r
+        <appender-ref ref="console"/>\r
+    </logger>\r
+\r
+    <logger name="org.opendaylight.groupbasedpolicy.renderer.ios_xe_provider.impl.manager.PolicyManagerZipImpl" 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
index ef2d52038df6657c8f8b03034b243db07581b56f..d092fbdeb0648dc11948785a6a5cde7c9f55b362 100755 (executable)
@@ -21,7 +21,6 @@
     <ovsdb.version>1.3.0-SNAPSHOT</ovsdb.version>
     <openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
     <liblldp.version>0.11.0-SNAPSHOT</liblldp.version>
-    <sfc.version>0.3.0-SNAPSHOT</sfc.version>
   </properties>
 
   <dependencies>
@@ -59,7 +58,6 @@
     <dependency>
       <groupId>org.opendaylight.sfc</groupId>
       <artifactId>sfc-provider</artifactId>
-      <version>${sfc.version}</version>
     </dependency>
     <!-- testing dependencies -->
     <dependency>
index 445a682d0864f99c582f3c7b8b2dc9137e1fbc84..5bbe432dc70d9962359cb833c794416f127e8764 100644 (file)
   <version>0.4.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
+  <properties>
+    <sfc.version>0.3.0-SNAPSHOT</sfc.version>
+  </properties>
+
+
   <modules>
     <module>ofoverlay</module>
     <module>faas</module>
         <scope>import</scope>
         <type>pom</type>
       </dependency>
+
+      <!-- sfc -->
+      <dependency>
+        <groupId>org.opendaylight.sfc</groupId>
+        <artifactId>sfc-provider</artifactId>
+        <version>${sfc.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.sfc</groupId>
+        <artifactId>sfc-model</artifactId>
+        <version>${sfc.version}</version>
+      </dependency>
     </dependencies>
   </dependencyManagement>