Initial commit. 63/25963/6
authorGabriel Robitaille-Montpetit <grmontpetit@inocybe.com>
Tue, 25 Aug 2015 14:17:02 +0000 (10:17 -0400)
committerGabriel Robitaille-Montpetit <grmontpetit@inocybe.com>
Tue, 25 Aug 2015 17:52:06 +0000 (13:52 -0400)
Change-Id: Idb0991baa044c783a09f56df51bafbe7694436dd
Signed-off-by: Gabriel Robitaille-Montpetit <grmontpetit@inocybe.com>
45 files changed:
.gitignore
api/pom.xml [new file with mode: 0755]
api/src/main/yang/cl-vcpe-mef.yang [new file with mode: 0755]
artifacts/pom.xml [new file with mode: 0755]
checkstyle.xml [new file with mode: 0755]
cli/pom.xml [new file with mode: 0755]
cli/src/main/java/org/opendaylight/vcpe/cli/EvcRemoveShellCommand.java [new file with mode: 0644]
cli/src/main/java/org/opendaylight/vcpe/cli/UniAddShellCommand.java [new file with mode: 0755]
cli/src/main/java/org/opendaylight/vcpe/cli/UniListShellCommand.java [new file with mode: 0755]
cli/src/main/java/org/opendaylight/vcpe/cli/UniRemoveShellCommand.java [new file with mode: 0755]
cli/src/main/java/org/opendaylight/vcpe/cli/UniShowShellCommand.java [new file with mode: 0755]
cli/src/main/resources/OSGI-INF/blueprint/commands.xml [new file with mode: 0755]
features/pom.xml [new file with mode: 0755]
features/src/main/features/features.xml [new file with mode: 0755]
impl/pom.xml [new file with mode: 0755]
impl/src/main/config/default-config.xml [new file with mode: 0755]
impl/src/main/java/org/opendaylight/vcpe/api/IVcpeConsoleProvider.java [new file with mode: 0755]
impl/src/main/java/org/opendaylight/vcpe/api/IVcpeDataChangeListener.java [new file with mode: 0755]
impl/src/main/java/org/opendaylight/vcpe/command/AbstractCreateCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/AbstractDeleteCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/AbstractUpdateCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/Command.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/EvcCreateCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/EvcDeleteCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/EvcUpdateCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/TransactionInvoker.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/UniCreateCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/UniDeleteCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/command/UniUpdateCommand.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/impl/EvcDataChangeListener.java [new file with mode: 0755]
impl/src/main/java/org/opendaylight/vcpe/impl/UniDataChangeListener.java [new file with mode: 0755]
impl/src/main/java/org/opendaylight/vcpe/impl/VcpeConstants.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/impl/VcpeDataChangeListener.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/vcpe/impl/VcpeMapper.java [new file with mode: 0755]
impl/src/main/java/org/opendaylight/vcpe/impl/VcpeProvider.java [new file with mode: 0755]
impl/src/main/java/org/opendaylight/vcpe/impl/VcpeUtils.java [new file with mode: 0644]
impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vcpe/impl/rev150622/VcpeModule.java [new file with mode: 0755]
impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vcpe/impl/rev150622/VcpeModuleFactory.java [new file with mode: 0755]
impl/src/main/yang/vcpe-impl.yang [new file with mode: 0755]
impl/src/test/java/org/opendaylight/vcpe/impl/VcpeProviderTest.java [new file with mode: 0755]
it/pom.xml [new file with mode: 0755]
karaf/pom.xml [new file with mode: 0755]
pom.xml [new file with mode: 0755]
resources/CableLabs-VCPE.postman_collection [new file with mode: 0755]
resources/documentation.adoc [new file with mode: 0644]

index 713bc0e2235d7213617d85473705738dd6c65399..b7089ba278d6c42b80573c3fe8200c874a4cfdf4 100644 (file)
@@ -1,6 +1,31 @@
-# Maven
-target/
-
-# OpenDaylight
-yang-gen-sal/
-yang-gen-config/
+*.class
+**/target
+bin/
+dist
+**/logs
+products
+repository
+workspace
+*~
+target
+target-ide
+.classpath
+.project
+.settings
+MANIFEST.MF
+*.ipr
+*.iml
+*.iws
+.idea
+xtend-gen
+yang-gen-config
+yang-gen-sal
+classes
+out/
+.externalToolBuilders
+maven-eclipse.xml
+.DS_STORE
+.metadata
+.checkstyle
+*.html
+maven-metadata-local.xml
diff --git a/api/pom.xml b/api/pom.xml
new file mode 100755 (executable)
index 0000000..07846ee
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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">
+  <parent>
+    <groupId>org.opendaylight.yangtools</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-api</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-yang-types-20130715</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-inet-types</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools.model</groupId>
+      <artifactId>ietf-topology</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/api/src/main/yang/cl-vcpe-mef.yang b/api/src/main/yang/cl-vcpe-mef.yang
new file mode 100755 (executable)
index 0000000..5276e6d
--- /dev/null
@@ -0,0 +1,149 @@
+/*\r
+ * Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL\r
+ */\r
+\r
+// Constructed based on Adolfo's UML UNI model\r
+// UNI\r
+// + uniIdentifier : string\r
+// + physicalMedium : string = UNI Type 2 Physical Interface\r
+// + speed : string = Set (10M, 100M, 10M/100M, 10M/100M/1000M, 1G, 10G>\r
+// + mode : string = Full Duplex\r
+// + macLayer : string = IEEE 802.3-2005\r
+// + type : string\r
+// + uniMtuSize : int = [uniMtuSize >= 1522]\r
+\r
+module cl-vcpe-mef {\r
+\r
+    yang-version 1;\r
+    namespace "urn:opendaylight:params:xml:ns:yang:vcpe";\r
+    prefix "vcpe";\r
+\r
+    import ietf-yang-types { prefix yang; revision-date 2013-07-15; }\r
+    import ietf-inet-types { prefix inet; revision-date 2010-09-24; }\r
+    import network-topology { prefix topo; revision-date 2013-10-21; }\r
+\r
+    revision "2015-06-22" {\r
+        description "Initial revision of vcpe model";\r
+    }\r
+\r
+    grouping service-speed {\r
+        choice speed {\r
+            case speed-10M {\r
+                leaf speed-10M {\r
+                    type empty;\r
+                }\r
+            }\r
+            case speed-100M {\r
+                leaf speed-100M {\r
+                    type empty;\r
+                }\r
+            }\r
+            case speed-1G {\r
+                leaf speed-1G {\r
+                    type empty;\r
+                }\r
+            }\r
+            case speed-10G {\r
+                leaf speed-10G {\r
+                    type empty;\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    // represent simplification of MEF Per Uni Attributes\r
+    grouping uni {\r
+        leaf id {\r
+            type topo:node-id;\r
+            mandatory true;\r
+            description "Uniquely identifies the uni";\r
+        }\r
+        leaf ovsdb-node-id {\r
+            type topo:node-id;\r
+            mandatory false;\r
+            description "Uniquely identifies the uni and ovsdb";\r
+        }\r
+        leaf physical-medium {\r
+            type string;\r
+            default "UNI TypeFull Duplex 2 Physical Interface";\r
+        }\r
+        leaf ip-address {\r
+            type inet:ip-address;\r
+        }\r
+        leaf mac-address {\r
+           type yang:mac-address;\r
+        }\r
+        container speed {\r
+            uses service-speed;\r
+        }\r
+        leaf mode {\r
+            type string;\r
+            default "Full Duplex";\r
+        }\r
+        leaf mac-layer {\r
+            type string;\r
+            default "IEEE 802.3-2005";\r
+        }\r
+        leaf type {\r
+            type string;\r
+        }\r
+        leaf mtu-size {\r
+            type uint64;\r
+            units byte;\r
+        }\r
+    }\r
+\r
+    // Represents simplification of MEF EVC Per Uni Atrributes\r
+    grouping evc {\r
+        leaf id {\r
+            type topo:node-id;\r
+            mandatory true;\r
+            description "Uniquely identifies the evc";\r
+        }\r
+        list uni-source {\r
+            key "order";\r
+            leaf order {\r
+                type uint8;\r
+            }\r
+            leaf uni {\r
+                type topo:node-id;\r
+            }\r
+        }\r
+        list uni-dest {\r
+            key "order";\r
+            leaf order {\r
+                type uint8;\r
+            }\r
+            leaf uni {\r
+                type topo:node-id;\r
+            }\r
+        }\r
+        leaf cos-id {\r
+            type string;\r
+        }\r
+        container ingress-bw {\r
+            uses service-speed;\r
+        }\r
+        container egress-bw {\r
+            uses service-speed;\r
+        }\r
+    }\r
+\r
+    container unis {\r
+        list uni {\r
+            key "id";\r
+            uses uni;\r
+        }\r
+    }\r
+\r
+    container evcs {\r
+        list evc {\r
+            key "id";\r
+            uses evc;\r
+        }\r
+    }\r
+}\r
diff --git a/artifacts/pom.xml b/artifacts/pom.xml
new file mode 100755 (executable)
index 0000000..8c9bd3e
--- /dev/null
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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>
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-artifacts</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>pom</packaging>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>vcpe-api</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>vcpe-impl</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>vcpe-features</artifactId>
+        <version>${project.version}</version>
+        <classifier>features</classifier>
+        <type>xml</type>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+</project>
diff --git a/checkstyle.xml b/checkstyle.xml
new file mode 100755 (executable)
index 0000000..daf4a17
--- /dev/null
@@ -0,0 +1,230 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+          "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+
+    Checkstyle configuration that checks the Google coding conventions from:
+
+    -  Google Java Style
+       https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html
+
+    Checkstyle is very configurable. Be sure to read the documentation at
+    http://checkstyle.sf.net (or in your downloaded distribution).
+
+    Most Checks are configurable, be sure to consult the documentation.
+
+    To completely disable a check, just comment it out or delete it from the file.
+
+    Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
+
+ -->
+
+<module name = "Checker">
+    <property name="charset" value="UTF-8"/>
+    <!-- Change to error to fail the build. Having severity here
+         ignores the FailsOnError setting in the pom.xml -->
+    <property name="severity" value="error"/>
+
+    <!-- Checks for whitespace                               -->
+    <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+        <module name="FileTabCharacter">
+            <property name="eachLine" value="true"/>
+        </module>
+
+    <module name="SuppressWarningsFilter"/>
+    <module name="TreeWalker">
+        <module name="SuppressWarningsHolder"/>
+        <module name="UnusedImports"/>
+        <module name="OuterTypeFilename"/>
+        <module name="IllegalTokenText">
+            <property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
+            <property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
+            <property name="message" value="Avoid using corresponding octal or Unicode escape."/>
+        </module>
+    <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+        <module name="AvoidEscapedUnicodeCharacters">
+            <property name="allowEscapesForControlCharacters" value="true"/>
+            <property name="allowByTailComment" value="true"/>
+            <property name="allowNonPrintableEscapes" value="true"/>
+        </module>
+    -->
+        <module name="LineLength">
+            <property name="max" value="120"/><!-- ODL projects use 120 max line length -->
+            <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
+        </module>
+        <module name="AvoidStarImport"/>
+    <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+        <module name="OneTopLevelClass"/>
+        <module name="NoLineWrap"/>
+    -->
+        <module name="EmptyBlock">
+            <property name="option" value="TEXT"/>
+            <property name="tokens" value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
+        </module>
+        <module name="NeedBraces"/>
+        <module name="LeftCurly">
+            <property name="maxLineLength" value="100"/>
+        </module>
+        <module name="RightCurly"/>
+        <module name="RightCurly">
+            <property name="option" value="alone"/>
+            <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
+        </module>
+        <module name="WhitespaceAround">
+            <property name="allowEmptyConstructors" value="true"/>
+            <property name="allowEmptyMethods" value="true"/>
+        <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+            <property name="allowEmptyTypes" value="true"/>
+            <property name="allowEmptyLoops" value="true"/>
+        -->
+            <message key="ws.notFollowed"
+             value="WhitespaceAround: ''{0}'' is not followed by whitespace."/>
+             <message key="ws.notPreceded"
+             value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
+        </module>
+        <module name="OneStatementPerLine"/>
+        <module name="MultipleVariableDeclarations"/>
+        <module name="ArrayTypeStyle"/>
+        <module name="MissingSwitchDefault"/>
+        <module name="FallThrough"/>
+        <module name="UpperEll"/>
+        <module name="ModifierOrder"/>
+    <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+        <module name="EmptyLineSeparator">
+            <property name="allowNoEmptyLineBetweenFields" value="true"/>
+        </module>
+        <module name="SeparatorWrap">
+            <property name="tokens" value="DOT"/>
+            <property name="option" value="nl"/>
+        </module>
+        <module name="SeparatorWrap">
+            <property name="tokens" value="COMMA"/>
+            <property name="option" value="EOL"/>
+        </module>
+    -->
+        <module name="PackageName">
+            <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
+            <message key="name.invalidPattern"
+             value="Package name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+        <module name="TypeName">
+            <message key="name.invalidPattern"
+             value="Type name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+        <module name="MemberName">
+            <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+            <message key="name.invalidPattern"
+             value="Member name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+        <module name="ParameterName">
+            <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+            <message key="name.invalidPattern"
+             value="Parameter name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+        <module name="LocalVariableName">
+            <property name="tokens" value="VARIABLE_DEF"/>
+            <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+        <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+            <property name="allowOneCharVarInForLoop" value="true"/>
+        -->
+            <message key="name.invalidPattern"
+             value="Local variable name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+        <module name="ClassTypeParameterName">
+            <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+            <message key="name.invalidPattern"
+             value="Class type name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+        <module name="MethodTypeParameterName">
+            <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+            <message key="name.invalidPattern"
+             value="Method type name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+        <module name="NoFinalizer"/>
+        <module name="GenericWhitespace">
+            <message key="ws.followed"
+             value="GenericWhitespace ''{0}'' is followed by whitespace."/>
+             <message key="ws.preceded"
+             value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
+             <message key="ws.illegalFollow"
+             value="GenericWhitespace ''{0}'' should followed by whitespace."/>
+             <message key="ws.notPreceded"
+             value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
+        </module>
+        <module name="Indentation">
+            <property name="basicOffset" value="4"/>
+            <property name="braceAdjustment" value="0"/>
+            <property name="caseIndent" value="4"/>
+            <property name="throwsIndent" value="4"/>
+        <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+            <property name="lineWrappingIndentation" value="4"/>
+            <property name="arrayInitIndent" value="4"/>
+        -->
+        </module>
+    <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+        <module name="AbbreviationAsWordInName">
+            <property name="ignoreFinal" value="false"/>
+            <property name="allowedAbbreviationLength" value="1"/>
+        </module>
+        <module name="OverloadMethodsDeclarationOrder"/>
+        <module name="VariableDeclarationUsageDistance"/>
+        <module name="CustomImportOrder">
+            <property name="thirdPartyPackageRegExp" value=".*"/>
+            <property name="specialImportsRegExp" value="com.google"/>
+            <property name="sortImportsInGroupAlphabetically" value="true"/>
+            <property name="customImportOrderRules" value="STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/>
+        </module>
+    -->
+        <module name="MethodParamPad"/>
+        <module name="OperatorWrap">
+            <property name="option" value="NL"/>
+            <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
+        </module>
+    <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+        <module name="AnnotationLocation">
+            <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
+        </module>
+        <module name="AnnotationLocation">
+            <property name="tokens" value="VARIABLE_DEF"/>
+            <property name="allowSamelineMultipleAnnotations" value="true"/>
+        </module>
+        <module name="NonEmptyAtclauseDescription"/>
+        <module name="JavadocTagContinuationIndentation"/>
+        <module name="SummaryJavadocCheck">
+            <property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
+        </module>
+        <module name="JavadocParagraph"/>
+        <module name="AtclauseOrder">
+            <property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
+            <property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
+        </module>
+    -->
+        <!--sh<module name="JavadocMethod">
+            <property name="scope" value="public"/>
+            <property name="allowMissingParamTags" value="true"/>
+            <property name="allowMissingThrowsTags" value="true"/>
+            <property name="allowMissingReturnTag" value="true"/>sh-->
+        <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+            <property name="minLineCount" value="2"/>
+            <property name="allowedAnnotations" value="Override, Test"/>
+        -->
+            <!--sh<property name="allowThrowsTagsForSubclasses" value="true"/>
+        </module>-->
+        <module name="MethodName">
+            <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
+            <message key="name.invalidPattern"
+             value="Method name ''{0}'' must match pattern ''{1}''."/>
+        </module>
+    <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+        <module name="SingleLineJavadoc"/>
+    -->
+
+    </module>
+
+    <!--<module name="RegexpHeader">
+        <property name="headerFile" value="${checkstyle.header.file}"/>
+        <property name="multiLines" value="2"/>
+    </module>-->
+</module>
diff --git a/cli/pom.xml b/cli/pom.xml
new file mode 100755 (executable)
index 0000000..389933a
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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">
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.4.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-cli</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+     <groupId>org.apache.karaf.shell</groupId>
+     <artifactId>org.apache.karaf.shell.console</artifactId>
+     <version>${karaf.version}</version>
+    </dependency>
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <configLocation>${project.basedir}/../checkstyle.xml</configLocation>
+          <failsOnError>true</failsOnError>
+          <includes>**/*.java,**/*.xml,**/*.ini,**/*.sh,**/*.bat</includes>
+          <excludes>**/yang/</excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/cli/src/main/java/org/opendaylight/vcpe/cli/EvcRemoveShellCommand.java b/cli/src/main/java/org/opendaylight/vcpe/cli/EvcRemoveShellCommand.java
new file mode 100644 (file)
index 0000000..b47a482
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vcpe.api.IVcpeConsoleProvider;
+
+@Command(name = "remove", scope = "Evc", description = "Removes Evc.")
+public class EvcRemoveShellCommand extends OsgiCommandSupport {
+
+    protected IVcpeConsoleProvider provider;
+
+    @Argument(index = 0, name = "id", description = "Evc Id", required = true, multiValued = false)
+    String id;
+
+    public EvcRemoveShellCommand(IVcpeConsoleProvider provider) {
+        this.provider = provider;
+    }
+
+    @Override
+    protected Object doExecute() throws Exception {
+        if (provider.removeEvc(id)) {
+            return String.format("Evc successfully removed");
+        } else {
+            return String.format("Error removing Evc");
+        }
+    }
+
+}
diff --git a/cli/src/main/java/org/opendaylight/vcpe/cli/UniAddShellCommand.java b/cli/src/main/java/org/opendaylight/vcpe/cli/UniAddShellCommand.java
new file mode 100755 (executable)
index 0000000..899211b
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.cli;
+
+import java.math.BigInteger;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vcpe.api.IVcpeConsoleProvider;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.service.speed.speed.Speed100MBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.service.speed.speed.Speed10GBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.service.speed.speed.Speed10MBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.service.speed.speed.Speed1GBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.uni.Speed;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.UniBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+
+@Command(name = "add",
+         scope = "uni",
+         description = "Adds an uni to the controller.")
+public class UniAddShellCommand extends OsgiCommandSupport {
+
+    protected IVcpeConsoleProvider provider;
+
+    @Option(name = "-id",
+            aliases = { "--uni-id" },
+            description = "The id.\n-id / --id <id>",
+            required = true,
+            multiValued = false)
+    private String uniId = "any";
+
+    @Option(name = "-pm",
+            aliases = { "--physical-medium" },
+            description = "The physical medium.\n-pm / --physical-medium <physical-medium>",
+            required = false,
+            multiValued = false)
+    private String physicalMedium = "any";
+
+    @Option(name = "-ma",
+            aliases = { "--mac-address" },
+            description = "The mac address.\n-ma / --mac-address <mac-address>",
+            required = false,
+            multiValued = false)
+    private String macAddress = "any";
+
+    @Option(name = "-m",
+            aliases = { "--mode" },
+            description = "The mode.\n-m / --mode <mode>",
+            required = false,
+            multiValued = false)
+    private String mode = "any";
+
+    @Option(name = "-ml",
+            aliases = { "--mac-layer" },
+            description = "The mac layer.\n-ml / --mac-layer <mac-layer",
+            required = false,
+            multiValued = false)
+    private String macLayer = "any";
+
+    @Option(name = "-t",
+            aliases = { "--type" },
+            description = "The type.\n-t / --type <type>",
+            required = false,
+            multiValued = false)
+    private String type = "any";
+
+    @Option(name = "-ms",
+            aliases = { "--mtu-size" },
+            description = "The mtu size.\n-ms / --mtu-size <mtu-size>",
+            required = false,
+            multiValued = false)
+    private String mtuSize;
+
+    @Option(name = "-s",
+            aliases = { "--speed" },
+            description = "Spped.\n-s / --speed 10M/100M/1G/10G",
+            required = true,
+            multiValued = true)
+    private String speed = "any";
+
+    public UniAddShellCommand(IVcpeConsoleProvider provider) {
+        this.provider = provider;
+    }
+
+    private Object getSpeed() {
+
+        System.out.println(speed);
+
+        Object speedObject = null;
+        if (speed.equals("10M")) {
+            System.out.println("there");
+            speedObject = new Speed10MBuilder().build();
+        }
+        if (speed.equals("100M")) {
+            speedObject = new Speed100MBuilder().build();
+        }
+        if (speed.equals("1G")) {
+            speedObject = new Speed1GBuilder().build();
+        }
+        if (speed.equals("10G")) {
+            speedObject = new Speed10GBuilder().build();
+        }
+        System.out.println(speedObject);
+        return speedObject;
+    }
+
+    @Override
+    protected Object doExecute() throws Exception {
+        Uni uni = new UniBuilder()
+                        .setMacAddress(new MacAddress(macAddress))
+                        .setMacLayer(macLayer)
+                        .setMode(mode)
+                        .setMtuSize(BigInteger.valueOf(Long.valueOf(mtuSize)))
+                        .setPhysicalMedium(physicalMedium)
+                        .setSpeed((Speed) getSpeed())
+                        .setType(type)
+                        .setId(new NodeId(uniId))
+                        .build();
+
+        if (provider.addUni(uni)) {
+            return String.format("Uni created (id: %s)", uni.getId());
+        } else {
+            return new String("Error creating new uni");
+        }
+    }
+}
diff --git a/cli/src/main/java/org/opendaylight/vcpe/cli/UniListShellCommand.java b/cli/src/main/java/org/opendaylight/vcpe/cli/UniListShellCommand.java
new file mode 100755 (executable)
index 0000000..570b6a1
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Inocybe 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.vcpe.cli;
+
+import java.util.List;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vcpe.api.IVcpeConsoleProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+
+@Command(name = "list", scope = "uni", description = "Lists all uni in the controller.")
+public class UniListShellCommand extends OsgiCommandSupport {
+
+    protected IVcpeConsoleProvider provider;
+
+    @Option(name = "-c",
+            aliases = { "--config" },
+            description = "List Configuration Data (optional).\n-c / --config <ENTER>",
+            required = false,
+            multiValued = false)
+    Boolean isConfigurationData = false;
+
+    public UniListShellCommand(IVcpeConsoleProvider provider) {
+        this.provider = provider;
+    }
+
+    @Override
+    protected Object doExecute() throws Exception {
+
+        List<Uni> listUnis = provider.listUnis(isConfigurationData);
+
+        if (listUnis.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            Integer counter = 1;
+            for (Uni uni : listUnis) {
+                sb.append(String.format("#%d - id: %s\n", counter, uni.getId()));
+                counter++;
+            }
+            return sb.toString();
+        } else {
+            return String.format("No uni found. Check the logs for more details.");
+        }
+    }
+}
diff --git a/cli/src/main/java/org/opendaylight/vcpe/cli/UniRemoveShellCommand.java b/cli/src/main/java/org/opendaylight/vcpe/cli/UniRemoveShellCommand.java
new file mode 100755 (executable)
index 0000000..7b3003c
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vcpe.api.IVcpeConsoleProvider;
+
+@Command(name = "remove", scope = "uni", description = "Removes an Uni from the controller.")
+public class UniRemoveShellCommand extends OsgiCommandSupport {
+
+    protected IVcpeConsoleProvider provider;
+
+    @Argument(index = 0, name = "id", description = "Uni Id", required = true, multiValued = false)
+    String id;
+
+    public UniRemoveShellCommand(IVcpeConsoleProvider provider) {
+        this.provider = provider;
+    }
+
+    @Override
+    protected Object doExecute() throws Exception {
+        if (provider.removeUni(id)) {
+            return String.format("Uni successfully removed");
+        } else {
+            return String.format("Error removing Uni");
+        }
+    }
+}
diff --git a/cli/src/main/java/org/opendaylight/vcpe/cli/UniShowShellCommand.java b/cli/src/main/java/org/opendaylight/vcpe/cli/UniShowShellCommand.java
new file mode 100755 (executable)
index 0000000..235d3ad
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vcpe.api.IVcpeConsoleProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+
+@Command(name = "show", scope = "uni", description = "Shows detailed information about an uni.")
+public class UniShowShellCommand extends OsgiCommandSupport {
+
+    protected IVcpeConsoleProvider provider;
+
+    @Argument(index = 0, name = "id", description = "Uni Id", required = true, multiValued = false)
+    String id;
+
+    public UniShowShellCommand(IVcpeConsoleProvider provider) {
+        this.provider = provider;
+    }
+
+    @Override
+    protected Object doExecute() throws Exception {
+        StringBuilder sb = new StringBuilder();
+        Uni uni = provider.getUni(id);
+
+        if (uni != null) {
+            sb.append(String.format("Uni Id: <%s>\n", uni.getId()));
+            sb.append(String.format("Physical medium: <%s>\n", uni.getPhysicalMedium()));
+            sb.append(String.format("Mac address: <%s>\n", uni.getMacAddress()));
+            sb.append(String.format("Speed: " + uni.getSpeed() + "\n"));
+            sb.append(String.format("Mode: <%s>\n", uni.getMode()));
+            sb.append(String.format("Mac layer: <%s>\n", uni.getMacLayer()));
+            sb.append(String.format("Type: <%s>\n", uni.getType()));
+            sb.append(String.format("Mtu size: <%s>\n", uni.getMtuSize()));
+            return sb.toString();
+        } else {
+            return String.format("No uni found. Check the logs for more details.");
+        }
+    }
+}
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/commands.xml b/cli/src/main/resources/OSGI-INF/blueprint/commands.xml
new file mode 100755 (executable)
index 0000000..2a2eb97
--- /dev/null
@@ -0,0 +1,35 @@
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+    <reference id="vcpeConsoleProvider" availability="mandatory"
+        activation="eager" interface="org.opendaylight.vcpe.api.IVcpeConsoleProvider">
+    </reference>
+
+    <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+        <command>
+            <action class="org.opendaylight.vcpe.cli.UniAddShellCommand">
+                <argument ref="vcpeConsoleProvider" />
+            </action>
+        </command>
+        <command>
+            <action class="org.opendaylight.vcpe.cli.UniRemoveShellCommand">
+                 <argument ref="vcpeConsoleProvider" />
+            </action>
+        </command>
+        <command>
+            <action class="org.opendaylight.vcpe.cli.UniListShellCommand">
+                 <argument ref="vcpeConsoleProvider" />
+            </action>
+        </command>
+        <command>
+            <action class="org.opendaylight.vcpe.cli.UniShowShellCommand" >
+                <argument ref="vcpeConsoleProvider" />
+            </action>
+        </command>
+        <command>
+            <action class="org.opendaylight.vcpe.cli.EvcRemoveShellCommand">
+                 <argument ref="vcpeConsoleProvider" />
+            </action>
+        </command>
+    </command-bundle>
+
+</blueprint>
diff --git a/features/pom.xml b/features/pom.xml
new file mode 100755 (executable)
index 0000000..a9ecaa6
--- /dev/null
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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">
+  <parent>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>features-parent</artifactId>
+    <version>1.6.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-features</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <mdsal.version>1.3.0-SNAPSHOT</mdsal.version>
+    <yangtools.version>0.8.0-SNAPSHOT</yangtools.version>
+    <dlux.version>0.3.0-SNAPSHOT</dlux.version>
+    <ovsdb.version>1.2.0-SNAPSHOT</ovsdb.version>
+    <configfile.directory>etc/opendaylight/karaf</configfile.directory>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <!-- project specific dependencies -->
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>mdsal-artifacts</artifactId>
+        <version>${mdsal.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>features-yangtools</artifactId>
+      <classifier>features</classifier>
+      <version>${yangtools.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-mdsal</artifactId>
+      <classifier>features</classifier>
+      <version>${mdsal.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>features-restconf</artifactId>
+      <classifier>features</classifier>
+      <version>${mdsal.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.dlux</groupId>
+      <artifactId>features-dlux</artifactId>
+      <classifier>features</classifier>
+      <version>${dlux.version}</version>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.ovsdb</groupId>
+      <artifactId>southbound-features</artifactId>
+      <version>${ovsdb.version}</version>
+      <type>xml</type>
+      <classifier>features</classifier>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-impl</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-impl</artifactId>
+      <version>${project.version}</version>
+      <type>xml</type>
+      <classifier>config</classifier>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+        <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml
new file mode 100755 (executable)
index 0000000..14abb3a
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 CableLabs
+
+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
+-->
+<features name="odl-vcpe-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+  <repository>mvn:org.opendaylight.yangtools/features-yangtools/${yangtools.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.controller/features-restconf/${mdsal.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.ovsdb/southbound-features/${ovsdb.version}/xml/features</repository>
+  <repository>mvn:org.opendaylight.dlux/features-dlux/${dlux.version}/xml/features</repository>
+
+  <feature name='odl-vcpe-api' version='${project.version}' description='OpenDaylight :: VCPE :: api'>
+    <feature version='${yangtools.version}'>odl-yangtools-models</feature>
+    <bundle>mvn:org.opendaylight.vcpe/vcpe-api/${project.version}</bundle>
+  </feature>
+
+  <feature name='odl-vcpe' version='${project.version}' description='OpenDaylight :: VCPE'>
+    <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+    <feature version='${ovsdb.version}'>odl-ovsdb-southbound-impl</feature>
+    <feature version='${project.version}'>odl-vcpe-api</feature>
+    <bundle>mvn:org.opendaylight.vcpe/vcpe-impl/${project.version}</bundle>
+    <configfile finalname="${configfile.directory}/vcpe.xml">mvn:org.opendaylight.vcpe/vcpe-impl/${project.version}/xml/config</configfile>
+  </feature>
+
+  <feature name='odl-vcpe-console' version='${project.version}' description='OpenDaylight :: VCPE :: CLI'>
+      <feature version="${project.version}">odl-vcpe</feature>
+      <bundle>mvn:org.opendaylight.vcpe/vcpe-cli/${project.version}</bundle>
+  </feature>
+
+  <feature name='odl-vcpe-rest' version='${project.version}' description='OpenDaylight :: VCPE :: REST'>
+    <feature version="${project.version}">odl-vcpe</feature>
+    <feature version="${mdsal.version}">odl-restconf</feature>
+  </feature>
+
+  <feature name='odl-vcpe-ui' version='${project.version}' description='OpenDaylight :: VCPE :: UI'>
+    <feature version="${project.version}">odl-vcpe-rest</feature>
+    <feature version="${project.version}">odl-vcpe-console</feature>
+    <feature version="${mdsal.version}">odl-mdsal-apidocs</feature>
+    <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+    <feature version="${dlux.version}">odl-dlux-all</feature>
+  </feature>
+
+</features>
diff --git a/impl/pom.xml b/impl/pom.xml
new file mode 100755 (executable)
index 0000000..c131c4e
--- /dev/null
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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">
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.4.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <properties>
+  <ovsdb.version>1.2.0-SNAPSHOT</ovsdb.version>
+  <powermock.version>1.5.2</powermock.version>
+  </properties>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-impl</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-api</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+<!--     OVSDB dependency -->
+    <dependency>
+      <groupId>org.opendaylight.ovsdb</groupId>
+      <artifactId>southbound-api</artifactId>
+      <version>${ovsdb.version}</version>
+    </dependency>
+
+    <!-- Testing Dependencies -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-all</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-core</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-module-junit4</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-mockito</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-api-support</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.powermock</groupId>
+      <artifactId>powermock-reflect</artifactId>
+      <version>${powermock.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <configLocation>${project.basedir}/../checkstyle.xml</configLocation>
+          <failsOnError>true</failsOnError>
+          <includes>**/*.java,**/*.xml,**/*.ini,**/*.sh,**/*.bat</includes>
+          <excludes>**/yang/</excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/impl/src/main/config/default-config.xml b/impl/src/main/config/default-config.xml
new file mode 100755 (executable)
index 0000000..83268b1
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<snapshot>
+  <required-capabilities>
+      <capability>urn:opendaylight:params:xml:ns:yang:vcpe:impl?module=vcpe-impl&amp;revision=2015-06-22</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:vcpe:impl">prefix:vcpe</type>
+          <name>vcpe-default</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/impl/src/main/java/org/opendaylight/vcpe/api/IVcpeConsoleProvider.java b/impl/src/main/java/org/opendaylight/vcpe/api/IVcpeConsoleProvider.java
new file mode 100755 (executable)
index 0000000..3fcbd0f
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.api;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.evcs.Evc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+
+public interface IVcpeConsoleProvider extends AutoCloseable {
+
+    public boolean addUni(Uni uni);
+
+    public boolean removeUni(String uuid);
+
+    public List<Uni> listUnis(boolean isConfigurationDatastore);
+
+    public Uni getUni(String uuid);
+
+    public boolean removeEvc(String uuid);
+
+    public boolean addEvc(Evc evc);
+
+    public Evc getEvc(String uuid);
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/api/IVcpeDataChangeListener.java b/impl/src/main/java/org/opendaylight/vcpe/api/IVcpeDataChangeListener.java
new file mode 100755 (executable)
index 0000000..3e79820
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.api;
+
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface IVcpeDataChangeListener extends DataChangeListener,
+        AutoCloseable {
+
+    public void create(Map<InstanceIdentifier<?>, DataObject> changes);
+
+    public void update(Map<InstanceIdentifier<?>, DataObject> changes);
+
+    public void delete(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes);
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/AbstractCreateCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/AbstractCreateCommand.java
new file mode 100644 (file)
index 0000000..e2e6002
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public abstract class AbstractCreateCommand implements Command {
+
+    protected Map<InstanceIdentifier<?>, DataObject> changes;
+    protected DataBroker dataBroker;
+
+    @Override
+    public abstract void execute();
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/AbstractDeleteCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/AbstractDeleteCommand.java
new file mode 100644 (file)
index 0000000..3ef87b3
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public abstract class AbstractDeleteCommand implements Command {
+
+    protected AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes;
+    protected DataBroker dataBroker;
+
+    @Override
+    public abstract void execute();
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/AbstractUpdateCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/AbstractUpdateCommand.java
new file mode 100644 (file)
index 0000000..c3505ca
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public abstract class AbstractUpdateCommand implements Command {
+
+    protected Map<InstanceIdentifier<?>, DataObject> changes;
+    protected DataBroker dataBroker;
+
+    @Override
+    public abstract void execute();
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/Command.java b/impl/src/main/java/org/opendaylight/vcpe/command/Command.java
new file mode 100644 (file)
index 0000000..c650621
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+public interface Command {
+
+    public void execute();
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/EvcCreateCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/EvcCreateCommand.java
new file mode 100644 (file)
index 0000000..f61af9f
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vcpe.impl.VcpeConstants;
+import org.opendaylight.vcpe.impl.VcpeMapper;
+import org.opendaylight.vcpe.impl.VcpeUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.evcs.Evc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class EvcCreateCommand extends AbstractCreateCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EvcCreateCommand.class);
+
+    public EvcCreateCommand(DataBroker dataBroker,
+            Map<InstanceIdentifier<?>, DataObject> changes) {
+        super.dataBroker = dataBroker;
+        super.changes = changes;
+    }
+
+    @Override
+    public void execute() {
+        for (Entry<InstanceIdentifier<?>, DataObject> created : changes
+                .entrySet()) {
+            if (created.getValue() != null && created.getValue() instanceof Evc) {
+                Evc evc = (Evc) created.getValue();
+                LOG.info("New EVC created with id {}.", evc.getId());
+                if (evc.getUniDest() == null || evc.getUniDest().isEmpty()) {
+                    LOG.error("Destination UNI cannot be null.");
+                    break;
+                }
+                if (evc.getUniSource() == null || evc.getUniSource().isEmpty()) {
+                    LOG.error("Source UNI cannot be null.");
+                    break;
+                }
+                // Get the destination UNI
+                NodeId destUniNodeID = evc.getUniDest().get(0).getUni();
+                InstanceIdentifier<Uni> destinationNodeIid = VcpeMapper.getUniIid(destUniNodeID);
+                Optional<Uni> optionalDestination = VcpeUtils.readUniNode(dataBroker, destinationNodeIid);
+                Uni destinationUni = optionalDestination.get();
+                NodeId ovsdbDestinationNodeId = VcpeMapper.createNodeId(destinationUni.getIpAddress());
+                // Get the source UNI
+                NodeId sourceUniNodeID = evc.getUniSource().get(0).getUni();
+                InstanceIdentifier<Uni> sourceNodeIid = VcpeMapper.getUniIid(sourceUniNodeID);
+                Optional<Uni> optionalSource = VcpeUtils.readUniNode(dataBroker, sourceNodeIid);
+                Uni sourceUni = optionalSource.get();
+                NodeId ovsdbSourceNodeId = VcpeMapper.createNodeId(sourceUni.getIpAddress());
+
+                // Set source
+                Node sourceBr1 = VcpeUtils.readNode(
+                        dataBroker,
+                        VcpeMapper.getOvsdbBridgeNodeIID(ovsdbSourceNodeId,
+                                VcpeConstants.DEFAULT_BRIDGE_NAME)).get();
+                VcpeUtils.createTerminationPointNode(dataBroker,
+                        destinationUni, sourceBr1,
+                        VcpeConstants.DEFAULT_BRIDGE_NAME,
+                        VcpeConstants.DEFAULT_INTERNAL_IFACE, null);
+                Node sourceBr2 = VcpeUtils.readNode(
+                        dataBroker,
+                        VcpeMapper.getOvsdbBridgeNodeIID(ovsdbSourceNodeId,
+                                VcpeConstants.DEFAULT_BRIDGE_NAME)).get();
+                VcpeUtils.createGreTunnel(dataBroker, sourceUni,
+                        destinationUni, sourceBr2,
+                        VcpeConstants.DEFAULT_BRIDGE_NAME, "gre0");
+
+                // Set destination
+                Node destinationBr1 = VcpeUtils.readNode(
+                        dataBroker,
+                        VcpeMapper.getOvsdbBridgeNodeIID(ovsdbDestinationNodeId,
+                                VcpeConstants.DEFAULT_BRIDGE_NAME)).get();
+                VcpeUtils.createTerminationPointNode(dataBroker,
+                        destinationUni, destinationBr1,
+                        VcpeConstants.DEFAULT_BRIDGE_NAME,
+                        VcpeConstants.DEFAULT_INTERNAL_IFACE, null);
+                Node destinationBr2 = VcpeUtils.readNode(
+                        dataBroker,
+                        VcpeMapper.getOvsdbBridgeNodeIID(ovsdbDestinationNodeId,
+                                VcpeConstants.DEFAULT_BRIDGE_NAME)).get();
+                VcpeUtils.createGreTunnel(dataBroker, destinationUni,
+                        sourceUni, destinationBr2,
+                        VcpeConstants.DEFAULT_BRIDGE_NAME, "gre0");
+            }
+        }
+    }
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/EvcDeleteCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/EvcDeleteCommand.java
new file mode 100644 (file)
index 0000000..a36bde5
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.vcpe.impl.VcpeUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Evc;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EvcDeleteCommand extends AbstractDeleteCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EvcDeleteCommand.class);
+
+    public EvcDeleteCommand(DataBroker dataBroker,
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        super.changes = changes;
+        super.dataBroker = dataBroker;
+    }
+
+    @Override
+    public void execute() {
+        Map<InstanceIdentifier<Evc>, Evc> originalEvcs = VcpeUtils.extractOriginal(changes, Evc.class);
+        Set<InstanceIdentifier<Evc>> removedEvcs = VcpeUtils.extractRemoved(changes, Evc.class);
+
+        Set<InstanceIdentifier<?>> removedPaths = changes.getRemovedPaths();
+        if (!removedPaths.isEmpty()) {
+            for (InstanceIdentifier<?> removedPath: removedPaths) {
+                Class<?> type = removedPath.getTargetType();
+                LOG.info("Removed paths instance identifier {}", type);
+                if (type.equals(Evc.class)) {
+                    LOG.info("Removed paths instance identifier {}", type);
+                    for (Entry<InstanceIdentifier<Evc>, Evc> evc: originalEvcs.entrySet()) {
+                        if (evc.getKey().equals(type)) {
+                            Evc data = evc.getValue();
+                            LOG.info("Removed EVC {}", data.getId());
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/EvcUpdateCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/EvcUpdateCommand.java
new file mode 100644 (file)
index 0000000..f3f3e22
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EvcUpdateCommand extends AbstractUpdateCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EvcUpdateCommand.class);
+
+    public EvcUpdateCommand(DataBroker dataBroker,
+            Map<InstanceIdentifier<?>, DataObject> changes) {
+        super.dataBroker = dataBroker;
+        super.changes = changes;
+    }
+
+    @Override
+    public void execute() {
+        LOG.info("Update has not been implemented yet.");
+    }
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/TransactionInvoker.java b/impl/src/main/java/org/opendaylight/vcpe/command/TransactionInvoker.java
new file mode 100644 (file)
index 0000000..3a69c4f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.List;
+
+public class TransactionInvoker {
+
+    private Command command;
+    private List<Command> commands;
+
+    public void setCommand(Command command) {
+        this.command = command;
+    }
+
+    public void setCommands(List<Command> commands) {
+        this.commands = commands;
+    }
+
+    public void invoke() {
+        if (command != null) {
+            command.execute();
+        }
+        if (!commands.isEmpty()) {
+            for (Command invokableCommand: commands) {
+                invokableCommand.execute();
+            }
+        }
+    }
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/UniCreateCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/UniCreateCommand.java
new file mode 100644 (file)
index 0000000..74e731b
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vcpe.impl.VcpeConstants;
+import org.opendaylight.vcpe.impl.VcpeMapper;
+import org.opendaylight.vcpe.impl.VcpeUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Unis;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+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.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class UniCreateCommand extends AbstractCreateCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(UniCreateCommand.class);
+
+    public UniCreateCommand(DataBroker dataBroker,
+            Map<InstanceIdentifier<?>, DataObject> changes) {
+        super.dataBroker = dataBroker;
+        super.changes = changes;
+    }
+
+    @Override
+    public void execute() {
+        for (Entry<InstanceIdentifier<?>, DataObject> created : changes.entrySet()) {
+            if (created.getValue() != null && created.getValue() instanceof Uni) {
+                Uni uni = (Uni) created.getValue();
+                LOG.info("New UNI created with id {}.", uni.getId());
+                /* We assume that when the user specifies the
+                 * ovsdb-node-id that the node already exists in
+                 * the controller and that the OVS instance is in
+                 * active mode.
+                 *
+                 * We assume that when the user doesn't specify the
+                 * ovsdb-node-id that the node doesn't exist therefor
+                 * has to be created with the IP address because it's
+                 * in passive mode.
+                 *
+                 * Active mode (TCP): the UUID is in format ovsdb://UUID
+                 * Passwove mode (PTCP): the UUID is in format ovsdb://IP:6640
+                 *
+                 */
+                NodeId ovsdbNodeId = uni.getOvsdbNodeId();
+                if (ovsdbNodeId == null || ovsdbNodeId.getValue().isEmpty()) {
+                    // We assume the ovs is in passive mode
+                    ovsdbNodeId = VcpeMapper.createNodeId(uni.getIpAddress());
+                }
+                // We retrieve the node from the store
+                Optional<Node> node = VcpeUtils.readNode(dataBroker, VcpeMapper.getOvsdbNodeIID(ovsdbNodeId));
+                if (!node.isPresent()) {
+                    VcpeUtils.createOvsdbNode(dataBroker, ovsdbNodeId, uni);
+                }
+            }
+            if (created.getValue() != null && created.getValue() instanceof OvsdbNodeAugmentation) {
+                OvsdbNodeAugmentation ovsdbNodeAugmentation = (OvsdbNodeAugmentation) created
+                        .getValue();
+                if (ovsdbNodeAugmentation != null) {
+                    LOG.info("Received an OVSDB node create {}",
+                            ovsdbNodeAugmentation.getConnectionInfo()
+                                    .getRemoteIp().getIpv4Address().getValue());
+                    Unis unis = VcpeUtils.readUnisFromStore(dataBroker, LogicalDatastoreType.CONFIGURATION);
+                    if (unis != null && unis.getUni() != null) {
+                        // This will not scale up very well when the UNI quantity gets to higher numbers.
+                        for (Uni uni: unis.getUni()) {
+                            if (uni.getOvsdbNodeId() != null && uni.getOvsdbNodeId().getValue() != null) {
+                                // The OVS instance is in tcp mode.
+                                NodeKey key = created.getKey().firstKeyOf(Node.class, NodeKey.class);
+                                if (uni.getOvsdbNodeId().equals(key.getNodeId())) {
+
+                                    VcpeUtils.createBridgeNode(dataBroker,
+                                            uni.getOvsdbNodeId(), uni,
+                                            VcpeConstants.DEFAULT_BRIDGE_NAME);
+
+                                    VcpeUtils.copyUniToDataStore(dataBroker, uni, LogicalDatastoreType.OPERATIONAL);
+                                }
+                                // The OVS instance is in ptcp mode.
+                            } else if (ovsdbNodeAugmentation
+                                            .getConnectionInfo()
+                                            .getRemoteIp()
+                                            .equals(uni.getIpAddress())) {
+                                InstanceIdentifier<Node> ovsdbNodeIid = VcpeMapper.getOvsdbNodeIID(uni.getIpAddress());
+                                Optional<Node> ovsdbNode = VcpeUtils.readNode(dataBroker, ovsdbNodeIid);
+                                NodeId ovsdbNodeId;
+                                if (ovsdbNode.isPresent()) {
+                                    ovsdbNodeId = ovsdbNode.get().getNodeId();
+                                    VcpeUtils.createBridgeNode(dataBroker,
+                                            ovsdbNodeId, uni,
+                                            VcpeConstants.DEFAULT_BRIDGE_NAME);
+
+                                    VcpeUtils.copyUniToDataStore(dataBroker, uni, LogicalDatastoreType.OPERATIONAL);
+                                } else {
+                                    LOG.error("Unable to read node with IID {}", ovsdbNodeIid);
+                                }
+                            }
+                        }
+                    } else {
+                        LOG.info("Received a new OVSDB node connection from {}"
+                                + ovsdbNodeAugmentation.getConnectionInfo()
+                                        .getRemoteIp().getIpv4Address());
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/UniDeleteCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/UniDeleteCommand.java
new file mode 100644 (file)
index 0000000..51a0c3b
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.vcpe.impl.VcpeUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Uni;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UniDeleteCommand extends AbstractDeleteCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(UniDeleteCommand.class);
+
+    public UniDeleteCommand(DataBroker dataBroker,
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        super.changes = changes;
+        super.dataBroker = dataBroker;
+    }
+
+    @Override
+    public void execute() {
+        Map<InstanceIdentifier<Uni>, Uni> originalUnis = VcpeUtils.extractOriginal(changes, Uni.class);
+        Set<InstanceIdentifier<Uni>> removedUnis = VcpeUtils.extractRemoved(changes, Uni.class);
+        if (!removedUnis.isEmpty()) {
+            for (InstanceIdentifier<Uni> removedUniIid: removedUnis) {
+                LOG.info("Received a request to remove an UNI ", removedUniIid);
+            }
+        }
+    }
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/command/UniUpdateCommand.java b/impl/src/main/java/org/opendaylight/vcpe/command/UniUpdateCommand.java
new file mode 100644 (file)
index 0000000..d49e485
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.command;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UniUpdateCommand extends AbstractUpdateCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(UniUpdateCommand.class);
+
+    public UniUpdateCommand(DataBroker dataBroker,
+            Map<InstanceIdentifier<?>, DataObject> changes) {
+        super.dataBroker = dataBroker;
+        super.changes = changes;
+    }
+
+    @Override
+    public void execute() {
+        for (Entry<InstanceIdentifier<?>, DataObject> created : changes
+                .entrySet()) {
+            if (created.getValue() != null
+                    && created.getValue() instanceof OvsdbNodeAugmentation) {
+                OvsdbNodeAugmentation ovsdbNodeAugmentation = (OvsdbNodeAugmentation) created
+                        .getValue();
+                if (ovsdbNodeAugmentation != null) {
+                    LOG.info("Received an OVSDB node create {}",
+                            ovsdbNodeAugmentation.getConnectionInfo()
+                                    .getRemoteIp().getIpv4Address().getValue());
+                    final List<ManagedNodeEntry> managedNodeEntries = ovsdbNodeAugmentation.getManagedNodeEntry();
+                    if (managedNodeEntries != null) {
+                        for (ManagedNodeEntry managedNodeEntry : managedNodeEntries) {
+                            LOG.info("Received an update from an OVSDB node {}.", managedNodeEntry.getKey());
+                            // We received a node update from the southbound plugin
+                            // so we have to check if it belongs to the UNI
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/impl/EvcDataChangeListener.java b/impl/src/main/java/org/opendaylight/vcpe/impl/EvcDataChangeListener.java
new file mode 100755 (executable)
index 0000000..81b2e2e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vcpe.api.IVcpeDataChangeListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EvcDataChangeListener implements IVcpeDataChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(EvcDataChangeListener.class);
+
+    private DataBroker dataBroker;
+    private ListenerRegistration<DataChangeListener> evcListener = null;
+
+    public EvcDataChangeListener(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        evcListener = dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.CONFIGURATION, VcpeMapper.getEvcsIid(),
+                this, DataChangeScope.SUBTREE);
+    }
+
+    @Override
+    public void onDataChanged(
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        create(changes.getCreatedData());
+        update(changes.getUpdatedData());
+        delete(changes);
+    }
+
+    @Override
+    public void create(Map<InstanceIdentifier<?>, DataObject> changes) {
+    }
+
+    @Override
+    public void update(Map<InstanceIdentifier<?>, DataObject> changes) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void delete(
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public void close() throws Exception {
+        if (evcListener != null) {
+            evcListener.close();
+        }
+    }
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/impl/UniDataChangeListener.java b/impl/src/main/java/org/opendaylight/vcpe/impl/UniDataChangeListener.java
new file mode 100755 (executable)
index 0000000..0260577
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vcpe.api.IVcpeDataChangeListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UniDataChangeListener implements IVcpeDataChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(UniDataChangeListener.class);
+
+    private Map<String, ListenerRegistration<DataChangeListener>> listeners;
+    private DataBroker dataBroker;
+
+    public UniDataChangeListener(DataBroker dataBroker) {
+        this.dataBroker = dataBroker;
+        listeners = new HashMap<String, ListenerRegistration<DataChangeListener>>();
+        ListenerRegistration<DataChangeListener> uniListener = dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.CONFIGURATION, VcpeMapper.getUnisIid()
+                , this, DataChangeScope.SUBTREE);
+        // We want to listen for operational store changes on the ovsdb:1 network topology
+        // because this is when we know Southbound has successfully connected to the
+        // OVS instance.
+        ListenerRegistration<DataChangeListener> ovsdbListener = dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.OPERATIONAL, VcpeMapper.getOvsdbTopologyIdentifier()
+                , this, DataChangeScope.SUBTREE);
+        listeners.put("uni", uniListener);
+        listeners.put("ovsdb", ovsdbListener);
+
+    }
+
+    @Override
+    public void onDataChanged(
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        create(changes.getCreatedData());
+        update(changes.getUpdatedData());
+        delete(changes);
+    }
+
+    @Override
+    public void create(Map<InstanceIdentifier<?>, DataObject> changes) {
+    }
+
+    @Override
+    public void update(Map<InstanceIdentifier<?>, DataObject> changes) {
+    }
+
+    @Override
+    public void delete(
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        // TODO implement delete, verify old data versus new data
+    }
+
+    @Override
+    public void close() throws Exception {
+        for (Map.Entry<String, ListenerRegistration<DataChangeListener>> entry : listeners.entrySet()) {
+            ListenerRegistration<DataChangeListener> value = entry.getValue();
+            if (value != null) {
+                value.close();
+            }
+        }
+    }
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeConstants.java b/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeConstants.java
new file mode 100644 (file)
index 0000000..ed98b15
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdk;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkr;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhost;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeDpdkvhostuser;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGeneve;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeInternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeIpsecGre64;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeLisp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypePatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeSystem;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeTap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow10;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow11;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow12;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow13;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow14;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolOpenflow15;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+
+import com.google.common.collect.ImmutableBiMap;
+
+public class VcpeConstants {
+
+    public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
+
+    public static final String OVSDB_PREFIX = "ovsdb://";
+
+    public static final Integer OVSDB_PORT = new Integer(6640);
+
+    public static final Integer OPENFLOW_PORT = new Integer(6633);
+
+    public static final Ipv4Address LOCAL_IP = new Ipv4Address("127.0.0.1");
+
+    public static final String DEFAULT_BRIDGE_NAME = "br0";
+
+//    public static final String DEFAULT_BRIDGE2_NAME = "br2";
+
+    public static final String DEFAULT_BRIDGE_NODE_ID_SUFFIX = "/bridge/";
+
+    public static final String DEFAULT_INTERNAL_IFACE = "eth1";
+
+    public static final String DEFAULT_TUNNEL_IFACE = "eth1";
+
+    public static final String DEFAULT_GRE_NAME = "gre";
+
+    public static final ImmutableBiMap<String, Class<? extends InterfaceTypeBase>> OVSDB_INTERFACE_TYPE_MAP
+        = new ImmutableBiMap.Builder<String, Class<? extends InterfaceTypeBase>>()
+            .put("internal", InterfaceTypeInternal.class)
+            .put("vxlan", InterfaceTypeVxlan.class)
+            .put("patch", InterfaceTypePatch.class)
+            .put("system", InterfaceTypeSystem.class)
+            .put("tap", InterfaceTypeTap.class)
+            .put("geneve", InterfaceTypeGeneve.class)
+            .put("gre", InterfaceTypeGre.class)
+            .put("ipsec_gre", InterfaceTypeIpsecGre.class)
+            .put("gre64", InterfaceTypeGre64.class)
+            .put("ipsec_gre64", InterfaceTypeIpsecGre64.class)
+            .put("lisp", InterfaceTypeLisp.class)
+            .put("dpdk", InterfaceTypeDpdk.class)
+            .put("dpdkr", InterfaceTypeDpdkr.class)
+            .put("dpdkvhost", InterfaceTypeDpdkvhost.class)
+            .put("dpdkvhostuser", InterfaceTypeDpdkvhostuser.class).build();
+
+    public static final ImmutableBiMap<Class<? extends OvsdbBridgeProtocolBase>, String> OVSDB_PROTOCOL_MAP
+        = new ImmutableBiMap.Builder<Class<? extends OvsdbBridgeProtocolBase>, String>()
+            .put(OvsdbBridgeProtocolOpenflow10.class, "OpenFlow10")
+            .put(OvsdbBridgeProtocolOpenflow11.class, "OpenFlow11")
+            .put(OvsdbBridgeProtocolOpenflow12.class, "OpenFlow12")
+            .put(OvsdbBridgeProtocolOpenflow13.class, "OpenFlow13")
+            .put(OvsdbBridgeProtocolOpenflow14.class, "OpenFlow14")
+            .put(OvsdbBridgeProtocolOpenflow15.class, "OpenFlow15").build();
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeDataChangeListener.java b/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeDataChangeListener.java
new file mode 100644 (file)
index 0000000..28ffee5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.vcpe.api.IVcpeDataChangeListener;
+import org.opendaylight.vcpe.command.Command;
+import org.opendaylight.vcpe.command.EvcCreateCommand;
+import org.opendaylight.vcpe.command.EvcDeleteCommand;
+import org.opendaylight.vcpe.command.EvcUpdateCommand;
+import org.opendaylight.vcpe.command.TransactionInvoker;
+import org.opendaylight.vcpe.command.UniCreateCommand;
+import org.opendaylight.vcpe.command.UniDeleteCommand;
+import org.opendaylight.vcpe.command.UniUpdateCommand;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VcpeDataChangeListener  implements IVcpeDataChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VcpeDataChangeListener.class);
+    private Map<String, ListenerRegistration<DataChangeListener>> listeners;
+    private DataBroker dataBroker;
+    private TransactionInvoker invoker;
+
+    public VcpeDataChangeListener(DataBroker dataBroker, TransactionInvoker invoker) {
+        this.dataBroker = dataBroker;
+        this.invoker = invoker;
+        listeners = new HashMap<String, ListenerRegistration<DataChangeListener>>();
+        ListenerRegistration<DataChangeListener> uniListener = dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.CONFIGURATION, VcpeMapper.getUnisIid()
+                , this, DataChangeScope.SUBTREE);
+        ListenerRegistration<DataChangeListener> evcListener = dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.CONFIGURATION, VcpeMapper.getEvcIid()
+                , this, DataChangeScope.SUBTREE);
+        ListenerRegistration<DataChangeListener> ovsdbListener = dataBroker.registerDataChangeListener(
+                LogicalDatastoreType.OPERATIONAL, VcpeMapper.getOvsdbTopologyIdentifier()
+                , this, DataChangeScope.SUBTREE);
+        listeners.put("uni", uniListener);
+        listeners.put("evc", evcListener);
+        listeners.put("ovsdb", ovsdbListener);
+    }
+
+    @Override
+    public void onDataChanged(
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        create(change.getCreatedData());
+        update(change.getUpdatedData());
+        delete(change);
+    }
+
+    @Override
+    public void create(Map<InstanceIdentifier<?>, DataObject> changes) {
+        if (changes != null) {
+            List<Command> commands = new ArrayList<Command>();
+            commands.add(new UniCreateCommand(dataBroker, changes));
+            commands.add(new EvcCreateCommand(dataBroker, changes));
+            invoker.setCommands(commands);
+            invoker.invoke();
+        }
+    }
+
+    @Override
+    public void update(Map<InstanceIdentifier<?>, DataObject> changes) {
+        if (changes != null) {
+            List<Command> commands = new ArrayList<Command>();
+            commands.add(new UniUpdateCommand(dataBroker, changes));
+            commands.add(new EvcUpdateCommand(dataBroker, changes));
+            invoker.setCommands(commands);
+            invoker.invoke();
+        }
+    }
+
+    @Override
+    public void delete(
+            AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changes) {
+        if (changes != null) {
+            List<Command> commands = new ArrayList<Command>();
+            commands.add(new UniDeleteCommand(dataBroker, changes));
+            commands.add(new EvcDeleteCommand(dataBroker, changes));
+            invoker.setCommands(commands);
+            invoker.invoke();
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("VcpeDataChangeListener stopped.");
+        for (Map.Entry<String, ListenerRegistration<DataChangeListener>> entry : listeners.entrySet()) {
+            ListenerRegistration<DataChangeListener> value = entry.getValue();
+            if (value != null) {
+                value.close();
+            }
+        }
+    }
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeMapper.java b/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeMapper.java
new file mode 100755 (executable)
index 0000000..301fc25
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Evcs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Unis;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.evcs.Evc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.evcs.EvcKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.UniKey;
+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.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+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.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VcpeMapper {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VcpeMapper.class);
+
+    public static InstanceIdentifier<Unis> getUnisIid() {
+        return InstanceIdentifier.builder(Unis.class)
+                .build();
+    }
+
+    public static InstanceIdentifier<Uni> getUniIid() {
+        return InstanceIdentifier.builder(Unis.class)
+                .child(Uni.class)
+                .build();
+    }
+
+    public static InstanceIdentifier<Uni> getUniIid(String id) {
+        return InstanceIdentifier.builder(Unis.class)
+                .child(Uni.class, new UniKey(new NodeId(id)))
+                .build();
+    }
+
+    public static InstanceIdentifier<Uni> getUniIid(UniKey uniKey) {
+        return InstanceIdentifier.builder(Unis.class)
+                .child(Uni.class, uniKey)
+                .build();
+    }
+
+    public static InstanceIdentifier<Uni> getUniIid(NodeId uniNodeId) {
+        return InstanceIdentifier.builder(Unis.class)
+                .child(Uni.class, new UniKey(uniNodeId))
+                .build();
+    }
+
+    public static InstanceIdentifier<Uni> getUniIid(Uni uni) {
+        return InstanceIdentifier.builder(Unis.class)
+                .child(Uni.class, uni.getKey())
+                .build();
+    }
+
+    public static InstanceIdentifier<Evcs> getEvcsIid() {
+        return InstanceIdentifier.builder(Evcs.class)
+                .build();
+    }
+
+    public static InstanceIdentifier<Evc> getEvcIid() {
+        return InstanceIdentifier.builder(Evcs.class)
+                .child(Evc.class)
+                .build();
+    }
+
+    public static InstanceIdentifier<Evc> getEvcIid(String id) {
+        return InstanceIdentifier.builder(Evcs.class)
+                .child(Evc.class, new EvcKey(new NodeId(id)))
+                .build();
+    }
+
+    public static InstanceIdentifier<Node> getOvsdbNodeIID(NodeId nodeId) {
+        InstanceIdentifier<Node> nodePath = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(VcpeConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class,new NodeKey(nodeId));
+        return nodePath;
+    }
+
+    public static InstanceIdentifier<Node> getOvsdbBridgeNodeIID(NodeId ovsdbNode, String bridgeName) {
+        NodeId bridgeNodeId = new NodeId(ovsdbNode + VcpeConstants.DEFAULT_BRIDGE_NODE_ID_SUFFIX + bridgeName);
+        InstanceIdentifier<Node> nodePath = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(VcpeConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class,new NodeKey(bridgeNodeId));
+        return nodePath;
+    }
+
+    public static InstanceIdentifier<Node> getOvsdbNodeIID(IpAddress ipAddress) {
+        String nodeId = VcpeConstants.OVSDB_PREFIX
+                + ipAddress.getIpv4Address().getValue().toString()
+                + ":"
+                + VcpeConstants.OVSDB_PORT;
+        InstanceIdentifier<Node> nodePath = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(VcpeConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class,new NodeKey(new NodeId(nodeId)));
+        return nodePath;
+    }
+
+    public static NodeId createNodeId(IpAddress ipAddress) {
+        String nodeId = VcpeConstants.OVSDB_PREFIX
+                + ipAddress.getIpv4Address().getValue().toString()
+                + ":"
+                + VcpeConstants.OVSDB_PORT;
+        return new NodeId(nodeId);
+    }
+
+    public static InstanceIdentifier<Node> getOvsdbTopologyIdentifier() {
+        InstanceIdentifier<Node> path = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class,
+                        new TopologyKey(VcpeConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class);
+        return path;
+    }
+
+    public static InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(
+            Node bridgeNode, String portName) {
+        InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
+                .create(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(VcpeConstants.OVSDB_TOPOLOGY_ID))
+                .child(Node.class,bridgeNode.getKey())
+                .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+
+        LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
+        return terminationPointPath;
+    }
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeProvider.java b/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeProvider.java
new file mode 100755 (executable)
index 0000000..cd469b0
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.vcpe.api.IVcpeConsoleProvider;
+import org.opendaylight.vcpe.command.TransactionInvoker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Evcs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.EvcsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Unis;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.UnisBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.evcs.Evc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class VcpeProvider implements BindingAwareProvider, AutoCloseable, IVcpeConsoleProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VcpeProvider.class);
+
+    private UniDataChangeListener vcpeDataChangeListener;
+    private EvcDataChangeListener evcDataChangeListener;
+    private VcpeDataChangeListener listener;
+    private TransactionInvoker invoker;
+
+    private DataBroker dataBroker;
+    private ServiceRegistration<IVcpeConsoleProvider> vcpeConsoleRegistration;
+
+    @Override
+    public void onSessionInitiated(ProviderContext session) {
+        LOG.info("VcpeProvider Session Initiated");
+
+        dataBroker =  session.getSALService(DataBroker.class);
+        invoker = new  TransactionInvoker();
+        // Initialize operational and default config data in MD-SAL data store
+        BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+        vcpeConsoleRegistration = context.registerService(IVcpeConsoleProvider.class, this, null);
+
+        vcpeDataChangeListener = new UniDataChangeListener(dataBroker);
+        evcDataChangeListener = new EvcDataChangeListener(dataBroker);
+        listener = new VcpeDataChangeListener(dataBroker, invoker);
+
+        // Init UNI Config & Operational stores
+        Unis unis = new UnisBuilder().build();
+        initDatastore(LogicalDatastoreType.CONFIGURATION, VcpeMapper.getUnisIid(), unis);
+        initDatastore(LogicalDatastoreType.OPERATIONAL, VcpeMapper.getUnisIid(), unis);
+        // Init EVC Config & Operational stores
+        Evcs evcs = new EvcsBuilder().build();
+        initDatastore(LogicalDatastoreType.CONFIGURATION, VcpeMapper.getEvcsIid(), evcs);
+        initDatastore(LogicalDatastoreType.OPERATIONAL, VcpeMapper.getEvcsIid(), evcs);
+    }
+
+    @Override
+    public void close() throws Exception {
+        LOG.info("VcpeProvider Closed");
+        vcpeConsoleRegistration.unregister();
+        vcpeDataChangeListener.close();
+        evcDataChangeListener.close();
+        listener.close();
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected void initDatastore(final LogicalDatastoreType store, InstanceIdentifier iid, final DataObject object) {
+        WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+        tx.put(store, iid, object);
+
+        // Perform the tx.submit asynchronously
+        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(final Void result) {
+                LOG.info("initStore {} with object {} succeeded", store, object);
+            }
+            @Override
+            public void onFailure(final Throwable throwable)  {
+                LOG.error("initStore {} with object {} failed", store, object);
+            }
+        });
+    }
+
+    @Override
+    public boolean addUni(Uni uni) {
+        Unis unis;
+        List<Uni> listOfUnis = listUnis(true);
+
+        try {
+            listOfUnis.add(uni);
+            unis = new UnisBuilder().setUni(listOfUnis).build();
+
+            // Place default config data in data store tree
+            WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+            tx.put(LogicalDatastoreType.CONFIGURATION, VcpeMapper.getUnisIid(), unis);
+
+            // Perform the tx.submit synchronously
+            tx.submit();
+        } catch (Exception e) {
+            LOG.error("addUni: failed: {}", e);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean removeUni(String id) {
+        try {
+            // Removes default config data in data store tree
+            WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+            tx.delete(LogicalDatastoreType.CONFIGURATION, VcpeMapper.getUniIid(id));
+            System.out.println(VcpeMapper.getUniIid(id));
+            // Perform the tx.submit synchronously
+            tx.submit();
+        } catch (Exception e) {
+            LOG.info("RemoveUni: failed: {}", e);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public List<Uni> listUnis(boolean isConfigurationDatastore) {
+        List<Uni> listOfUnis = null;
+
+        try {
+            ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction();
+            listOfUnis = tx.read((isConfigurationDatastore) ? LogicalDatastoreType.CONFIGURATION
+                    : LogicalDatastoreType.OPERATIONAL, VcpeMapper.getUnisIid()).checkedGet().get().getUni();
+        } catch (Exception e) {
+            LOG.error("ListIntents: failed: {}", e);
+        }
+
+        if (listOfUnis == null) {
+            listOfUnis = new ArrayList<Uni>();
+        }
+        LOG.info("ListUnisConfiguration: list of unis retrieved sucessfully");
+        return listOfUnis;
+    }
+
+    @Override
+    public Uni getUni(String id) {
+        Uni uni = null;
+
+        try {
+            InstanceIdentifier<Uni> iid = VcpeMapper.getUniIid(id);
+            System.out.println(VcpeMapper.getUniIid(id));
+
+            ReadOnlyTransaction tx = dataBroker.newReadOnlyTransaction();
+            uni = tx.read(LogicalDatastoreType.CONFIGURATION, iid).checkedGet().get();
+
+            if (uni == null) {
+                uni = tx.read(LogicalDatastoreType.OPERATIONAL, iid).checkedGet().get();
+            }
+        } catch (Exception e) {
+            LOG.error("getUni: failed: {}", e);
+            return null;
+        }
+        LOG.info("getUni: Uni retrieved sucessfully");
+        return uni;
+    }
+
+    @Override
+    public boolean removeEvc(String uuid) {
+        try {
+            WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+            tx.delete(LogicalDatastoreType.CONFIGURATION, VcpeMapper.getEvcIid(uuid));
+            System.out.println(VcpeMapper.getEvcIid(uuid));
+            tx.submit();
+        } catch (Exception e) {
+            LOG.info("Remove Evc: failed: {}", e);
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean addEvc(Evc evc) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public Evc getEvc(String uuid) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+}
diff --git a/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeUtils.java b/impl/src/main/java/org/opendaylight/vcpe/impl/VcpeUtils.java
new file mode 100644 (file)
index 0000000..c40cd43
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.CheckedFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.Unis;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.rev150622.unis.Uni;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+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.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VcpeUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VcpeUtils.class);
+
+    public static final Optional<Node> readNode(DataBroker dataBroker,
+            InstanceIdentifier<Node> nodeIid) {
+        ReadTransaction read = dataBroker.newReadOnlyTransaction();
+        CheckedFuture<Optional<Node>, ReadFailedException> nodeFuture = read
+                .read(LogicalDatastoreType.OPERATIONAL, nodeIid);
+        Optional<Node> nodeOptional;
+        try {
+            nodeOptional = nodeFuture.get();
+            return nodeOptional;
+        } catch (InterruptedException e) {
+            return Optional.absent();
+        } catch (ExecutionException e) {
+            return Optional.absent();
+        }
+    }
+
+    public static final Optional<Uni> readUniNode(DataBroker dataBroker,
+            InstanceIdentifier<Uni> nodeIid) {
+        ReadTransaction read = dataBroker.newReadOnlyTransaction();
+        CheckedFuture<Optional<Uni>, ReadFailedException> nodeFuture = read
+                .read(LogicalDatastoreType.OPERATIONAL, nodeIid);
+        Optional<Uni> nodeOptional;
+        try {
+            nodeOptional = nodeFuture.get();
+            return nodeOptional;
+        } catch (InterruptedException e) {
+            return Optional.absent();
+        } catch (ExecutionException e) {
+            return Optional.absent();
+        }
+    }
+
+    // This might not scale up.
+    public static final Unis readUnisFromStore(DataBroker dataBroker,
+            LogicalDatastoreType storetype) {
+        ReadOnlyTransaction read = dataBroker.newReadOnlyTransaction();
+        Optional<Unis> dataObject = null;
+        try {
+            dataObject = read.read(storetype,
+                    VcpeMapper.getUnisIid()).get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Error retrieving the UNIs from the Configuration tree.");
+        }
+        if ((dataObject != null) && (dataObject.get() != null)) {
+            read.close();
+            return dataObject.get();
+        } else {
+            read.close();
+            return null;
+        }
+    }
+
+    public static void copyUniToDataStore(DataBroker dataBroker, Uni uni,
+            LogicalDatastoreType dataStoreType) {
+        WriteTransaction write = dataBroker.newWriteOnlyTransaction();
+        write.put(dataStoreType, VcpeMapper.getUniIid(uni), uni);
+        write.submit();
+    }
+
+    public static OvsdbBridgeAugmentation createOvsdbBridgeAugmentation(Uni uni) {
+        NodeId ovsdbNodeId = uni.getOvsdbNodeId();
+        InstanceIdentifier<Node> ovsdbNodeIid;
+        if (ovsdbNodeId == null || ovsdbNodeId.getValue().isEmpty()) {
+            ovsdbNodeIid = VcpeMapper.getOvsdbNodeIID(uni.getIpAddress());
+        } else {
+            ovsdbNodeIid = VcpeMapper.getOvsdbNodeIID(ovsdbNodeId);
+        }
+        OvsdbNodeRef ovsdbNodeRef = new OvsdbNodeRef(ovsdbNodeIid);
+        UUID bridgeUuid = UUID.randomUUID();
+        OvsdbBridgeAugmentation ovsdbBridge = new OvsdbBridgeAugmentationBuilder()
+                    .setBridgeName(new OvsdbBridgeName(VcpeConstants.DEFAULT_BRIDGE_NAME))
+                    .setManagedBy(ovsdbNodeRef)
+                    .setBridgeUuid(new Uuid(bridgeUuid.toString()))
+                    .build();
+        return ovsdbBridge;
+    }
+
+    public static OvsdbNodeAugmentation createOvsdbNodeAugmentation(Uni uni) {
+        ConnectionInfo connectionInfos = new ConnectionInfoBuilder()
+                .setRemoteIp(uni.getIpAddress())
+                .setRemotePort(new PortNumber(VcpeConstants.OVSDB_PORT))
+                .build();
+        OvsdbNodeAugmentation ovsdbNode = new OvsdbNodeAugmentationBuilder()
+                .setConnectionInfo(connectionInfos).build();
+        return ovsdbNode;
+    }
+
+    public static OvsdbTerminationPointAugmentation createOvsdbTerminationPointAugmentation(Uni uni) {
+        // we will use nodeId to set interface port id
+        VlanId vlanID = new VlanId(1);
+        OvsdbTerminationPointAugmentation terminationPoint = new OvsdbTerminationPointAugmentationBuilder()
+                                                                     .setName(VcpeConstants.DEFAULT_INTERNAL_IFACE)
+                                                                     .setVlanTag(vlanID)
+                                                                     .setVlanMode(VlanMode.Access)
+                                                                     .build();
+        return terminationPoint;
+    }
+
+    public static IpAddress getLocalIp() {
+        String ip;
+        try {
+            ip = InetAddress.getLocalHost().getHostAddress();
+            Ipv4Address ipv4 = new Ipv4Address(ip);
+            IpAddress ipAddress = new IpAddress(ipv4);
+            return ipAddress;
+        } catch (UnknownHostException e) {
+            LOG.info("Unable to retrieve controller's ip address, using loopback.");
+        }
+        return new IpAddress(VcpeConstants.LOCAL_IP);
+    }
+
+    public static ConnectionInfo getConnectionInfo(DataBroker dataBroker, NodeId ovsdbNodeId) {
+        InstanceIdentifier<Node> nodeIid = VcpeMapper.getOvsdbNodeIID(ovsdbNodeId);
+        Optional<Node> node = readNode(dataBroker, nodeIid);
+        if (node.isPresent()) {
+            Node ovsdbNode = node.get();
+            OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
+            ConnectionInfo connectionInfo = ovsdbNodeAugmentation.getConnectionInfo();
+            return connectionInfo;
+        } else {
+            return null;
+        }
+    }
+
+    public static List<ControllerEntry> createControllerEntries(String targetString) {
+        List<ControllerEntry> controllerEntries = new ArrayList<ControllerEntry>();
+        ControllerEntryBuilder controllerEntryBuilder = new ControllerEntryBuilder();
+        controllerEntryBuilder.setTarget(new Uri(targetString));
+        controllerEntries.add(controllerEntryBuilder.build());
+        return controllerEntries;
+    }
+
+    public static List<ProtocolEntry> createMdsalProtocols() {
+        List<ProtocolEntry> protocolList = new ArrayList<ProtocolEntry>();
+        ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
+                VcpeConstants.OVSDB_PROTOCOL_MAP.inverse();
+        protocolList.add(new ProtocolEntryBuilder().
+                setProtocol((Class<? extends OvsdbBridgeProtocolBase>) mapper.get("OpenFlow13")).build());
+        return protocolList;
+    }
+
+    public static void createOvsdbNode(DataBroker dataBroker, NodeId ovsdbNodeId, Uni uni) {
+        InstanceIdentifier<Node> ovsdbNodeIid = VcpeMapper
+                .getOvsdbNodeIID(uni.getIpAddress());
+        try {
+            NodeKey ovsdbNodeKey = new NodeKey(ovsdbNodeId);
+            Node nodeData = new NodeBuilder().setNodeId(ovsdbNodeId)
+                    .setKey(ovsdbNodeKey)
+                    .addAugmentation(OvsdbNodeAugmentation.class, VcpeUtils.createOvsdbNodeAugmentation(uni))
+                    .build();
+            // Submit the node to the datastore
+            WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+            transaction.put(LogicalDatastoreType.CONFIGURATION, ovsdbNodeIid,
+                    nodeData);
+            transaction.submit();
+            LOG.info("Created and submitted a new OVSDB node {}",
+                    nodeData.getNodeId());
+        } catch (Exception e) {
+            LOG.error("Exception while creating OvsdbNodeAugmentation, "
+                    + "Uni is null. Node Id: {}", ovsdbNodeId);
+        }
+    }
+
+    public static void createBridgeNode(DataBroker dataBroker, NodeId ovsdbNodeId, Uni uni, String bridgeName) {
+        LOG.info("Creating a bridge on node {}", ovsdbNodeId);
+        InstanceIdentifier<Node> ovsdbNodeIid = VcpeMapper
+                .getOvsdbNodeIID(uni.getIpAddress());
+        ConnectionInfo connectionInfo = VcpeUtils.getConnectionInfo(dataBroker, ovsdbNodeId);
+        if (connectionInfo != null) {
+            NodeBuilder bridgeNodeBuilder = new NodeBuilder();
+            InstanceIdentifier<Node> bridgeIid = VcpeMapper
+                    .getOvsdbBridgeNodeIID(ovsdbNodeId, bridgeName);
+            NodeId bridgeNodeId = new NodeId(ovsdbNodeId
+                    + VcpeConstants.DEFAULT_BRIDGE_NODE_ID_SUFFIX + bridgeName);
+            bridgeNodeBuilder.setNodeId(bridgeNodeId);
+            OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
+            // String target = VcpeUtils.getLocalIp().toString();
+            // ovsdbBridgeAugmentationBuilder.setControllerEntry(VcpeUtils.createControllerEntries(target));
+            ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(
+                    bridgeName));
+            ovsdbBridgeAugmentationBuilder.setProtocolEntry(VcpeUtils
+                    .createMdsalProtocols());
+            OvsdbNodeRef ovsdbNodeRef = new OvsdbNodeRef(ovsdbNodeIid);
+            ovsdbBridgeAugmentationBuilder.setManagedBy(ovsdbNodeRef);
+            bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
+                    ovsdbBridgeAugmentationBuilder.build());
+            WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+            transaction.put(LogicalDatastoreType.CONFIGURATION, bridgeIid,
+                    bridgeNodeBuilder.build());
+            transaction.submit();
+        } else {
+            LOG.error("The OVSDB node is not connected {}", ovsdbNodeId);
+        }
+    }
+
+    public static void createTerminationPointNode(DataBroker dataBroker, Uni uni,
+            Node bridgeNode, String bridgeName, String portName, String type) {
+        InstanceIdentifier<TerminationPoint> tpIid = VcpeMapper
+                .createTerminationPointInstanceIdentifier(bridgeNode, portName);
+        OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
+                new OvsdbTerminationPointAugmentationBuilder();
+        tpAugmentationBuilder.setName(portName);
+        if (type != null) {
+            tpAugmentationBuilder.setInterfaceType(VcpeConstants.OVSDB_INTERFACE_TYPE_MAP.get(type));
+        }
+        TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+        tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+        tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+        transaction.put(LogicalDatastoreType.CONFIGURATION,tpIid,tpBuilder.build());
+        transaction.submit();
+    }
+
+    public static void createGreTunnel(DataBroker dataBroker, Uni source, Uni destination,
+            Node bridgeNode, String bridgeName, String portName) {
+        InstanceIdentifier<TerminationPoint> tpIid = VcpeMapper
+                .createTerminationPointInstanceIdentifier(bridgeNode, portName);
+        OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder =
+                new OvsdbTerminationPointAugmentationBuilder();
+        tpAugmentationBuilder.setName(portName);
+        ArrayList<Options> options = Lists.newArrayList();
+        OptionsKey optionKey = new OptionsKey("remote_ip");
+        Options destinationIp = new OptionsBuilder()
+                                        .setOption(destination.getIpAddress().getIpv4Address().getValue())
+                                        .setKey(optionKey)
+                                        .setValue(destination.getIpAddress().getIpv4Address().getValue())
+                                        .build();
+        options.add(destinationIp);
+        tpAugmentationBuilder.setOptions(options);
+        tpAugmentationBuilder.setInterfaceType(VcpeConstants.OVSDB_INTERFACE_TYPE_MAP.get("gre"));
+        TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+        tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+        tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+        WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+        transaction.put(LogicalDatastoreType.CONFIGURATION,tpIid,tpBuilder.build());
+        transaction.submit();
+    }
+
+    public static <T extends DataObject> Set<InstanceIdentifier<T>> extractRemoved(
+            AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
+        Set<InstanceIdentifier<T>> result = new HashSet<InstanceIdentifier<T>>();
+        if (changes != null && changes.getRemovedPaths() != null) {
+            for (InstanceIdentifier<?> iid : changes.getRemovedPaths()) {
+                if (iid.getTargetType().equals(klazz)) {
+                    @SuppressWarnings("unchecked") // Actually checked above
+                    InstanceIdentifier<T> iidn = (InstanceIdentifier<T>)iid;
+                    result.add(iidn);
+                }
+            }
+        }
+        return result;
+    }
+
+    public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extractOriginal(
+            AsyncDataChangeEvent<InstanceIdentifier<?>,DataObject> changes,Class<T> klazz) {
+        return extract(changes.getOriginalData(),klazz);
+    }
+
+    public static <T extends DataObject> Map<InstanceIdentifier<T>,T> extract(
+            Map<InstanceIdentifier<?>, DataObject> changes, Class<T> klazz) {
+        Map<InstanceIdentifier<T>,T> result = new HashMap<InstanceIdentifier<T>,T>();
+        if (changes != null && changes.entrySet() != null) {
+            for (Entry<InstanceIdentifier<?>, DataObject> created : changes.entrySet()) {
+                if (klazz.isInstance(created.getValue())) {
+                    @SuppressWarnings("unchecked")
+                    T value = (T) created.getValue();
+                    Class<?> type = created.getKey().getTargetType();
+                    if (type.equals(klazz)) {
+                        @SuppressWarnings("unchecked") // Actually checked above
+                        InstanceIdentifier<T> iid = (InstanceIdentifier<T>) created.getKey();
+                        result.put(iid, value);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+}
diff --git a/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vcpe/impl/rev150622/VcpeModule.java b/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vcpe/impl/rev150622/VcpeModule.java
new file mode 100755 (executable)
index 0000000..29821cd
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.impl.rev150622;
+
+import org.opendaylight.vcpe.impl.VcpeProvider;
+
+public class VcpeModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.impl.rev150622.AbstractVcpeModule {
+    public VcpeModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public VcpeModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.impl.rev150622.VcpeModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        final VcpeProvider vcpeProvider = new VcpeProvider();
+        getBrokerDependency().registerProvider(vcpeProvider);
+        return vcpeProvider;
+    }
+
+}
diff --git a/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vcpe/impl/rev150622/VcpeModuleFactory.java b/impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vcpe/impl/rev150622/VcpeModuleFactory.java
new file mode 100755 (executable)
index 0000000..b700a90
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: vcpe-impl yang module local name: vcpe
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Jun 22 15:07:08 EDT 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.impl.rev150622;
+public class VcpeModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vcpe.impl.rev150622.AbstractVcpeModuleFactory {
+
+}
diff --git a/impl/src/main/yang/vcpe-impl.yang b/impl/src/main/yang/vcpe-impl.yang
new file mode 100755 (executable)
index 0000000..16118ff
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+ */
+module vcpe-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:vcpe:impl";
+    prefix "vcpe-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+    description
+        "Service definition for vcpe project";
+
+    revision "2015-06-22" {
+        description
+            "Initial revision";
+    }
+
+    identity vcpe {
+        base config:module-type;
+        config:java-name-prefix Vcpe;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case vcpe {
+            when "/config:modules/config:module/config:type = 'vcpe'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/impl/src/test/java/org/opendaylight/vcpe/impl/VcpeProviderTest.java b/impl/src/test/java/org/opendaylight/vcpe/impl/VcpeProviderTest.java
new file mode 100755 (executable)
index 0000000..aba262f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 CableLabs 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.vcpe.impl;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vcpe.command.TransactionInvoker;
+import org.osgi.framework.FrameworkUtil;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({FrameworkUtil.class})
+public class VcpeProviderTest {
+
+    @Mock private UniDataChangeListener vcpeDataChangeListener;
+    @Mock private EvcDataChangeListener evcDataChangeListener;
+    @Mock private VcpeDataChangeListener listener;
+    @Mock private TransactionInvoker invoker;
+    @Mock private DataBroker dataBroker;
+
+    @Test
+    public void testClose() throws Exception {
+//        PowerMockito.mockStatic(FrameworkUtil.class);
+//        BundleContext context = mock(BundleContext.class);
+//        //ServiceRegistration registration = mock(ServiceRegistration.class);
+//        VcpeProvider provider = new VcpeProvider();
+//        Bundle bundle = mock(Bundle.class);
+//        PowerMockito.when(FrameworkUtil.getBundle(any(Class.class))).thenReturn(bundle);
+//        when(bundle.getBundleContext()).thenReturn(context);
+//        provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
+//        provider.close();
+    }
+}
diff --git a/it/pom.xml b/it/pom.xml
new file mode 100755 (executable)
index 0000000..a0aec96
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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">
+
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.4.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-it</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>jar</packaging>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>vcpe-artifacts</artifactId>
+        <version>${project.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller</groupId>
+        <artifactId>config-artifacts</artifactId>
+        <version>0.3.0-SNAPSHOT</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>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-features</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <configuration>
+          <configLocation>${project.basedir}/../checkstyle.xml</configLocation>
+          <failsOnError>true</failsOnError>
+          <includes>**/*.java,**/*.xml,**/*.ini,**/*.sh,**/*.bat</includes>
+          <excludes>**/yang/</excludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/karaf/pom.xml b/karaf/pom.xml
new file mode 100755 (executable)
index 0000000..6216089
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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">
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>karaf-parent</artifactId>
+    <version>1.6.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-karaf</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <name>${project.artifactId}</name>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <properties>
+    <karaf.localFeature>odl-vcpe-ui</karaf.localFeature>
+  </properties>
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>${project.groupId}</groupId>
+        <artifactId>vcpe-artifacts</artifactId>
+        <version>${project.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+  <dependencies>
+    <dependency>
+      <!-- scope is compile so all features (there is only one) are installed
+      into startup.properties and the feature repo itself is not installed -->
+      <groupId>org.apache.karaf.features</groupId>
+      <artifactId>framework</artifactId>
+      <type>kar</type>
+    </dependency>
+
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>vcpe-features</artifactId>
+      <classifier>features</classifier>
+      <type>xml</type>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+  <!-- DO NOT install or deploy the karaf artifact -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/pom.xml b/pom.xml
new file mode 100755 (executable)
index 0000000..db3f046
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Cable Television Laboratories, Inc. 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 INTERNAL
+-->
+<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">
+
+  <parent>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>odlparent</artifactId>
+    <version>1.6.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <groupId>org.opendaylight.vcpe</groupId>
+  <artifactId>vcpe-aggregator</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <name>vcpe</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <modules>
+    <module>api</module>
+    <module>impl</module>
+    <module>cli</module>
+    <module>it</module>
+    <module>karaf</module>
+    <module>features</module>
+    <module>artifacts</module>
+  </modules>
+  <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/vcpe.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/vcpe.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/vcpe:Main</url>
+  </scm>
+</project>
diff --git a/resources/CableLabs-VCPE.postman_collection b/resources/CableLabs-VCPE.postman_collection
new file mode 100755 (executable)
index 0000000..bad8d2b
--- /dev/null
@@ -0,0 +1,380 @@
+{
+       "id": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+       "name": "CableLabs - VCPE",
+       "timestamp": 1435073523712,
+       "order": [
+               "da7925e2-4f37-1e0e-d3cf-a536fb795171",
+               "14ac1a2d-9306-d7c7-49f4-ba35951e7a1e",
+               "6accd9eb-025b-210e-08aa-3e248ddaa0c4",
+               "13a342d7-87c9-60c1-7e49-53fc2106ebaf",
+               "965633be-5900-4c3c-4244-2631e149cddf",
+               "d5ea0824-9252-4d79-883f-da62c79748f6",
+               "e9ab5021-b477-2b2d-0cfc-8829bb30b415",
+               "f00f4893-a335-b2bd-a81c-15348298b325",
+               "3bd397f3-ccdf-2b9f-70af-5132ae7cf79e",
+               "d49d5d88-9aee-bfff-6431-a7e07dd01d8f",
+               "2847f959-8552-f9d5-bc33-14a530ad3e04",
+               "cb1cff17-1dc2-1b8a-997c-e2db8653a813",
+               "29bdb39e-6d5f-2a3c-abdf-df70d168a828",
+               "c9e45c17-136d-402c-a040-6d27bcd852d7",
+               "adccae4b-960a-643f-7659-4bd220cbae16",
+               "528504b1-80c2-60a6-0ec0-f117e5f0af73",
+               "8f1ee121-e98d-2685-2b67-dadbf80a8c81",
+               "2e6c8205-48eb-babf-8c21-6f8ee99120fe",
+               "e166c6e7-df44-bdf0-7a8c-24697cd5eb8a"
+       ],
+       "owner": 0,
+       "hasRequests": true,
+       "requests": [
+               {
+                       "id": "13a342d7-87c9-60c1-7e49-53fc2106ebaf",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/822f7eec-2b35-11e5-b345-feff819cdc9f",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "urlencoded",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436994678558,
+                       "name": "Delete Config UNI",
+                       "description": "Note: you have to specify the id of the UNI at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "14ac1a2d-9306-d7c7-49f4-ba35951e7a1e",
+                       "headers": "Content-Type: Application/json\nAuthorization: Basic YWRtaW46YWRtaW4=\nAccept: Application/json\n",
+                       "url": "http://localhost:8080/restconf/config/cl-vcpe-mef:unis/uni/822f7eec-2b35-11e5-b345-feff819cdc9f/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "PUT",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436995514307,
+                       "name": "Put Config UNI {ID}",
+                       "description": "Note: you have to specify the id of the UNI at the end of the URL and in the payload",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "rawModeData": "{\n    \"uni\": {\n      \"uni:id\": \"822f7eec-2b35-11e5-b345-feff819cdc9f\",\n        \"speed\": {\n            \"speed-1G\": 1\n        },\n        \"uni:mac-layer\": \"IEEE 802.3-2005\",\n        \"uni:physical-medium\": \"UNI TypeFull Duplex 2 Physical Interface\",\n        \"uni:mtu-size\": 0,\n        \"uni:type\": \"\",\n        \"uni:mac-address\": \"68:5b:35:bb:f8:3e\",\n        \"uni:ip-address\": \"192.168.0.22\",\n        \"uni:mode\": \"Full Duplex\"\n    }\n}"
+               },
+               {
+                       "id": "2847f959-8552-f9d5-bc33-14a530ad3e04",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/operational/cl-vcpe-mef:single-operator-evc/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054129280,
+                       "name": "Get Operational EVC {ID}",
+                       "description": "Note: you have to specify the id of the EVC at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "responses": []
+               },
+               {
+                       "id": "29bdb39e-6d5f-2a3c-abdf-df70d168a828",
+                       "headers": "Content-Type: Application/json\nAuthorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/822f8554-2b35-11e5-b345-feff819cdc9f/egress-bw/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "PUT",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054280230,
+                       "name": "Put Config EVC {ID} egress-bw",
+                       "description": "Note: you have to specify the id of the EVC at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "rawModeData": "{\n    \"egress-bw\": {\n        \"speed-1G\": [\n            null\n        ]\n    }\n}"
+               },
+               {
+                       "id": "2e6c8205-48eb-babf-8c21-6f8ee99120fe",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/e94c5ed4-2bc0-11e5-b345-feff819cdc9f/ingress-bw/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054369462,
+                       "name": "Delete Config EVC {ID} ingress-bw",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "rawModeData": "{\n    \"ingress-bw\": {\n        \"speed-1G\": [\n            null\n        ]\n    }\n}"
+               },
+               {
+                       "id": "3bd397f3-ccdf-2b9f-70af-5132ae7cf79e",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054225036,
+                       "name": "Get Config EVCs",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "responses": []
+               },
+               {
+                       "id": "528504b1-80c2-60a6-0ec0-f117e5f0af73",
+                       "headers": "Content-Type: application/json\nAuthorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/e94c5ed4-2bc0-11e5-b345-feff819cdc9f/ingress-bw/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "PUT",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054340369,
+                       "name": "Put Config EVC {ID} ingress-bw",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "rawModeData": "{\n    \"ingress-bw\": {\n        \"speed-1G\": [\n            null\n        ]\n    }\n}"
+               },
+               {
+                       "id": "6accd9eb-025b-210e-08aa-3e248ddaa0c4",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/822f7eec-2b35-11e5-b345-feff819cdc9f",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436995446302,
+                       "name": "Get Config UNI {ID}",
+                       "description": "Note: you have to specify the id of the UNI at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "8f1ee121-e98d-2685-2b67-dadbf80a8c81",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/e94c5ed4-2bc0-11e5-b345-feff819cdc9f/ingress-bw/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054352427,
+                       "name": "Get Config EVC {ID} ingress-bw",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "965633be-5900-4c3c-4244-2631e149cddf",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/822f7eec-2b35-11e5-b345-feff819cdc9f/speed/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436995498785,
+                       "name": "Get Config UNI {ID} speed",
+                       "description": "Note: you have to specify the id of the UNI at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "adccae4b-960a-643f-7659-4bd220cbae16",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/822f8554-2b35-11e5-b345-feff819cdc9f/egress-bw/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "urlencoded",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054307421,
+                       "name": "Delete Config EVC {ID} egress-bw",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "c9e45c17-136d-402c-a040-6d27bcd852d7",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/822f8554-2b35-11e5-b345-feff819cdc9f/egress-bw/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054293387,
+                       "name": "Get Config EVC {ID} egress-bw",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "cb1cff17-1dc2-1b8a-997c-e2db8653a813",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/822f8284-2b35-11e5-b345-feff819cdc9f",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "urlencoded",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054241062,
+                       "name": "Delete Config EVC {ID}",
+                       "description": "Note: you have to specify the id of the EVC at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "d49d5d88-9aee-bfff-6431-a7e07dd01d8f",
+                       "headers": "Content-Type: application/json\nAccept: application/json\nAuthorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/822f8284-2b35-11e5-b345-feff819cdc9f",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "PUT",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054105615,
+                       "name": "Put Config EVC {ID}",
+                       "description": "Note: you have to specify the id of the EVC at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "rawModeData": "{\n    \"evc\": {\n      \"evc:id\": \"822f8284-2b35-11e5-b345-feff819cdc9f\",\n      \"evc:uni-dest\": [\n            {\n                \"order\": 0,\n                \"uni\": \"\"\n            }\n        ],\n      \"evc:uni-source\": [\n            {\n                \"order\": 0,\n                \"uni\": \"\"\n            }\n        ],\n      \"evc:cos-id\": \"string\",\n      \"evc:ingress-bw\": {\n            \"speed-1G\": {}\n        },\n      \"evc:egress-bw\": {\n            \"speed-1G\": {}\n        }\n    }\n}"
+               },
+               {
+                       "id": "d5ea0824-9252-4d79-883f-da62c79748f6",
+                       "headers": "Content-Type: Application/json\nAuthorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/822f7eec-2b35-11e5-b345-feff819cdc9f/speed/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "PUT",
+                       "data": [],
+                       "dataMode": "raw",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436995608722,
+                       "name": "Put Config UNI {ID} speed",
+                       "description": "Note: you have to specify the id of the UNI at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac",
+                       "rawModeData": "{\n    \"speed\": {\n        \"speed-10G\": [\n            1\n        ]\n    }\n}"
+               },
+               {
+                       "id": "da7925e2-4f37-1e0e-d3cf-a536fb795171",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/json\nContent-Type: application/json\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:unis/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436995403134,
+                       "name": "Get Config UNIs",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "e166c6e7-df44-bdf0-7a8c-24697cd5eb8a",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8080/restconf/operational/cl-vcpe-mef:unis/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436988807365,
+                       "name": "Get Operational UNI",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "e9ab5021-b477-2b2d-0cfc-8829bb30b415",
+                       "headers": "Authorization: Basic YWRtaW46YWRtaW4=\n",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:single-operator-evc/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "GET",
+                       "data": [],
+                       "dataMode": "params",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1437054047739,
+                       "name": "Get Config single operator evc",
+                       "description": "",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               },
+               {
+                       "id": "f00f4893-a335-b2bd-a81c-15348298b325",
+                       "headers": "",
+                       "url": "http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/822f7eec-2b35-11e5-b345-feff819cdc9f/speed/",
+                       "preRequestScript": "",
+                       "pathVariables": {},
+                       "method": "DELETE",
+                       "data": [],
+                       "dataMode": "urlencoded",
+                       "version": 2,
+                       "tests": "",
+                       "currentHelper": "normal",
+                       "helperAttributes": {},
+                       "time": 1436995639501,
+                       "name": "Delete Config UNI {ID} speed",
+                       "description": "Note: you have to specify the id of the UNI at the end of the URL",
+                       "collectionId": "db7f3a0c-758b-93b2-42d2-4adef1c61bac"
+               }
+       ]
+}
\ No newline at end of file
diff --git a/resources/documentation.adoc b/resources/documentation.adoc
new file mode 100644 (file)
index 0000000..f73c444
--- /dev/null
@@ -0,0 +1,248 @@
+= Cable Labs VCPE
+
+== Information
+This document is geared towards documenting the VCPE project.
+
+== Content
+- Deployment Guide: How to install ODL with the plug-in
+- API Endpoint
+
+== Deployment guide
+=== Prerequisites:
+- Maven >= 3.1.1
+- Java JDK 1.7
+
+=== Steps:
+1. git clone https://git.opendaylight.org/gerrit/odlparent
+2. cd odlparent
+3. git checkout stable/lithium
+4. mvn clean install
+5. cd ..
+6. git clone https://git.opendaylight.org/gerrit/yangtools
+7. cd yangtools
+8. git checkout stable/lithium
+9. mvn clean install
+10. cd ..
+11. git clone git clone https://git.opendaylight.org/gerrit/controller
+12. git checkout stable/lithium
+13. cd controller
+14. mvn clean install
+15. cd ..
+16. git clone cable-labs-vcpe
+17. cd cable-labs-vcpe
+18. mvn clean install -DskipTests
+19. cd karaf/target
+20. tar xf vcpe-karaf-0.0.1-SNAPSHOT.tar.gz **or** unzip vcpe-karaf-0.0.1-SNAPSHOT.zip (windows)
+21. ./vcpe-karaf-0.0.1-SNAPSHOT/bin/karaf
+22. That should bring up the controller CLI, let it load for 1 minute, then the Postman collection can be used to create the UNIs/EVC 
+
+=== Usage
+Couple of points to keep in mind:
+
+- When creating a UNI, it is important to specify if the OpenVSwitch instance is running in TCP or PTCP mode.
+- The uni:id *must* always be unique for UNIs and EVCs. It was designed to be flexible and can be a UUID or something human readable, as long as it's unique.
+- The uni mac-address is the address of the OVS instance.
+- The mac address is the physical port of the OVS instance.
+- In these examples, the OVS instance is running in PTCP mode so we do not have to specify the UUID of the OVSDB node. However, when it is in TCP mode, it *must* be specified, like so:
+
+----
+{
+    "uni": {
+      "uni:id": "822f7eec-2b35-11e5-b345-feff819cdc9f",
+        "speed": {
+            "speed-1G": 1
+        },
+        "uni:ovsdb-node-id": "7978e1d5-31f9-4853-b6f9-2ea8eb3170a4",
+        "uni:mac-layer": "IEEE 802.3-2005",
+        "uni:physical-medium": "UNI TypeFull Duplex 2 Physical Interface",
+        "uni:mtu-size": 0,
+        "uni:type": "",
+        "uni:mac-address": "08:00:27:35:64:90",
+        "uni:ip-address": "192.168.1.30",
+        "uni:mode": "Full Duplex"
+    }
+}
+----
+
+==== Create UNI 1
+Using the Postman collection, create the first UNI:
+PUT
+----
+http://localhost:8080/restconf/config/cl-vcpe-mef:unis/uni/822f7eec-2b35-11e5-b345-feff819cdc9f/
+----
+Payload
+----
+{
+    "uni": {
+      "uni:id": "822f7eec-2b35-11e5-b345-feff819cdc9f",
+        "speed": {
+            "speed-1G": 1
+        },
+        "uni:mac-layer": "IEEE 802.3-2005",
+        "uni:physical-medium": "UNI TypeFull Duplex 2 Physical Interface",
+        "uni:mtu-size": 0,
+        "uni:type": "",
+        "uni:mac-address": "08:00:27:35:64:90",
+        "uni:ip-address": "192.168.1.30",
+        "uni:mode": "Full Duplex"
+    }
+}
+----
+==== Create UNI 2
+Using the Postman collection, create the second UNI:
+PUT
+----
+http://localhost:8080/restconf/config/cl-vcpe-mef:unis/uni/111f7eec-2c35-11e5-b345-feff819cdc9f/
+----
+Payload
+----
+{
+    "uni": {
+      "uni:id": "111f7eec-2c35-11e5-b345-feff819cdc9f",
+        "speed": {
+            "speed-1G": 1
+        },
+        "uni:mac-layer": "IEEE 802.3-2005",
+        "uni:physical-medium": "UNI TypeFull Duplex 2 Physical Interface",
+        "uni:mtu-size": 0,
+        "uni:type": "",
+        "uni:mac-address": "08:00:27:35:64:90",
+        "uni:ip-address": "192.168.1.30",
+        "uni:mode": "Full Duplex"
+    }
+}
+----
+==== Create EVC
+Using the Postman collection, create the first EVC:
+PUT
+----
+http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/822f8284-2b35-11e5-b345-feff819cdc9f
+----
+Payload
+----
+{
+    "evc": {
+      "evc:id": "822f8284-2b35-11e5-b345-feff819cdc9f",
+      "evc:uni-dest": [
+            {
+                "order": 0,
+                "uni": "822f7eec-2b35-11e5-b345-feff819cdc9f"
+            }
+        ],
+      "evc:uni-source": [
+            {
+                "order": 0,
+                "uni": "111f7eec-2c35-11e5-b345-feff819cdc9f"
+            }
+        ],
+      "evc:cos-id": "string",
+      "evc:ingress-bw": {
+            "speed-1G": {}
+        },
+      "evc:egress-bw": {
+            "speed-1G": {}
+        }
+    }
+}
+----
+== APIs
+This section contains a table with the VCPE APIs. For the current demo, **only the GET UNI / EVC and PUT UNI / EVC are currently implemented**.
+
+Note: The UNI and EVC UUID can be anything since we modelled it to be used in a flexible manner. It *must* always be unique
+
+.Api
+[width="100%",frame="topbot",options="header"]
+|======================
+| Store Type |Endpoint | Type | Payload | Return Code | Sample Return | Description
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:unis/' | GET | N/A | 200 | {
+    "unis": {
+        "uni": [
+            {
+                "id": "822f7eec-2b35-11e5-b345-feff819cdc9f",
+                "type": "",
+                "speed": {
+                    "speed-1G": [
+                        null
+                    ]
+                },
+                "ip-address": "192.168.1.30",
+                "physical-medium": "UNI TypeFull Duplex 2 Physical Interface",
+                "mode": "Full Duplex",
+                "mac-address": "08:00:27:35:64:90",
+                "mtu-size": 0,
+                "mac-layer": "IEEE 802.3-2005"
+            }
+        ]
+    }
+} | Get a list of Unis.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/\{UUID\}/' | PUT | {
+    "uni": {
+      "uni:id": "{UUID}",
+        "speed": {
+            "speed-1G": 1
+        },
+        "uni:mac-layer": "IEEE 802.3-2005",
+        "uni:physical-medium": "UNI TypeFull Duplex 2 Physical Interface",
+        "uni:mtu-size": 0,
+        "uni:type": "",
+        "uni:mac-address": "68:5b:35:bb:f8:3e",
+        "uni:ip-address": "192.168.0.22",
+        "uni:mode": "Full Duplex"
+    }
+} | 200 | N/A | Submit a new UNI
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/\{UUID\}' | GET | N/A | 200 | {
+    "uni": [
+        {
+            "id": "822f7eec-2b35-11e5-b345-feff819cdc9f",
+            "type": "",
+            "speed": {
+                "speed-1G": [
+                    null
+                ]
+            },
+            "ip-address": "192.168.1.30",
+            "physical-medium": "UNI TypeFull Duplex 2 Physical Interface",
+            "mode": "Full Duplex",
+            "mac-address": "08:00:27:35:64:90",
+            "mtu-size": 0,
+            "mac-layer": "IEEE 802.3-2005"
+        }
+    ]
+} | Get a specific UNI by its UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/\{UUID\}' | DELETE | N/A | 200 | N/A | Delete a specific UNI by its UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/\{UUID\}/speed/' | GET | N/A | 200 | {
+    "speed": {
+        "speed-1G": [
+            null
+        ]
+    }
+} | Get a specific UNI speed by its UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:unis/uni/\{UUID\}/speed/' | PUT | {
+    "speed": {
+        "speed-10G": [
+            1
+        ]
+    }
+} | 200 | N/A | Configure speed for a specific UNI by its UUID. The speed can also be specified in the creation of the UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:single-operator-evc/' | GET | N/A | 200 |  | Get the single-operator EVC.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/\{UUID\}' | DELETE | N/A | 200 |  | Delete an EVC by its UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/\{UUID\}/egress-bw/' | PUT | {
+    "egress-bw": {
+        "speed-1G": [
+            null
+        ]
+    }
+} | 200 |  | Add egress-bw to an EVC
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/\{UUID\}/egress-bw/' | GET | N/A | 200 |  | Get the agress-bw field from an EVC via its UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/\{UUID\}/egress-bw/' | DELETE | N/A | 200 |  | Delete egress-bw from EVC using the EVC UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/\{UUID\}/ingress-bw/' | PUT | {
+    "ingress-bw": {
+        "speed-1G": [
+            null
+        ]
+    }
+} | 200 |  | Set the ingress-bw of a specific EVC by its UUID.
+| Config | 'http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/\{UUID\}/ingress-bw/' | GET | N/A | 200 |  | Get a specific ingress-bw by the EVC UUID.
+| Config |'http://localhost:8181/restconf/config/cl-vcpe-mef:evcs/evc/\{UUID\}/ingress-bw/' | DELETE | N/A | 200 |  | Delete the ingress-bw from the EVC by specifying the EVC UUID.
+| Operational | 'http://localhost:8181/restconf/operational/cl-vcpe-mef:unis/' | GET | N/A | 200 |  | Get a list of UNIs within the Operational store.
+|======================