Initial commit for project. 95/6295/4
authorRob Adams <readams@readams.net>
Mon, 21 Apr 2014 15:50:27 +0000 (08:50 -0700)
committerRob Adams <readams@readams.net>
Tue, 6 May 2014 19:28:17 +0000 (12:28 -0700)
  * Creates maven project skeleton
  * Adds first-cut yang models for endpoint registry and policy
    repository
  * Adds first-cut basic service provider for endpoint registry.

Change-Id: I56382bd55057812f90ea906ac5e6e4ad02d6d9dc
Signed-off-by: Rob Adams <readams@readams.net>
13 files changed:
.gitignore [new file with mode: 0644]
commons/parent/pom.xml [new file with mode: 0644]
groupbasedpolicy/.gitignore [new file with mode: 0644]
groupbasedpolicy/pom.xml [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/endpoint_provider/impl/EndpointProviderModule.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/endpoint_provider/impl/EndpointProviderModuleFactory.java [new file with mode: 0644]
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/endpoint/EndpointRegistry.java [new file with mode: 0644]
groupbasedpolicy/src/main/yang/common.yang [new file with mode: 0644]
groupbasedpolicy/src/main/yang/endpoint-provider-impl.yang [new file with mode: 0644]
groupbasedpolicy/src/main/yang/endpoint-provider.yang [new file with mode: 0644]
groupbasedpolicy/src/main/yang/endpoint.yang [new file with mode: 0644]
groupbasedpolicy/src/main/yang/policy.yang [new file with mode: 0644]
pom.xml [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..474ad8f
--- /dev/null
@@ -0,0 +1,17 @@
+.idea/
+target/
+*.class
+*.iml
+**/target
+**/bin
+dist
+**/logs
+products
+repository
+workspace
+*~
+target
+.classpath
+.project
+.settings
+MANIFEST.MF
diff --git a/commons/parent/pom.xml b/commons/parent/pom.xml
new file mode 100644 (file)
index 0000000..cd32bd4
--- /dev/null
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.2-SNAPSHOT</version>
+  </parent>
+  <groupId>org.opendaylight.groupbasedpolicy</groupId>
+  <artifactId>commons.groupbasedpolicy</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <properties>
+    <java.version.source>1.7</java.version.source>
+    <java.version.target>1.7</java.version.target>
+    <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <configuration>
+            <source>${java.version.source}</source>
+            <target>${java.version.target}</target>
+            <testSource>${java.version.source}</testSource>
+            <testTarget>${java.version.target}</testTarget>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+  <url>https://wiki.opendaylight.org/view/Group_Policy:Main</url>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/groupbasedpolicy.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/groupbasedpolicy.git</developerConnection>
+    <tag>HEAD</tag>
+  </scm>
+  <repositories>
+    <!-- Opendaylight public group -->
+    <repository>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+      <id>opendaylight-public</id>
+      <name>opendaylight-public</name>
+      <url>${nexusproxy}/groups/public/</url>
+    </repository>
+    <!-- OpenDayLight Released artifact -->
+    <repository>
+      <id>opendaylight-release</id>
+      <name>opendaylight-release</name>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.release/</url>
+    </repository>
+    <!-- OpenDayLight Snapshot artifact -->
+    <repository>
+      <id>opendaylight-snapshot</id>
+      <name>opendaylight-snapshot</name>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
+    </repository>
+  </repositories>
+
+  <pluginRepositories>
+    <pluginRepository>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+      <id>opendaylight-public</id>
+      <name>opendaylight-public</name>
+      <url>http://nexus.opendaylight.org/content/groups/public/</url>
+    </pluginRepository>
+    <pluginRepository>
+      <id>opendaylight-release</id>
+      <name>central2</name>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.release/</url>
+    </pluginRepository>
+    <pluginRepository>
+      <id>opendaylight-snapshot</id>
+      <name>central2</name>
+      <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
+    </pluginRepository>
+  </pluginRepositories>
+</project>
diff --git a/groupbasedpolicy/.gitignore b/groupbasedpolicy/.gitignore
new file mode 100644 (file)
index 0000000..a48e45b
--- /dev/null
@@ -0,0 +1 @@
+/target-ide
diff --git a/groupbasedpolicy/pom.xml b/groupbasedpolicy/pom.xml
new file mode 100644 (file)
index 0000000..3ebd029
--- /dev/null
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.groupbasedpolicy</groupId>
+    <artifactId>groupbasedpolicy.project</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+
+  <artifactId>groupbasedpolicy</artifactId>
+  <packaging>bundle</packaging>
+
+  <properties>
+    <sal.version>1.1-SNAPSHOT</sal.version>
+    <yangtools.binding.version>0.6.2-SNAPSHOT</yangtools.binding.version>
+    <yangtools.generator.version>0.6.2-SNAPSHOT</yangtools.generator.version>
+    <yangtools.version>0.6.2-SNAPSHOT</yangtools.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.google.collections</groupId>
+      <artifactId>google-collections</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>config-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-binding-config</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal-common-util</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller.model</groupId>
+      <artifactId>model-inventory</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-binding</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>*</Import-Package>
+            <Export-Package>org.opendaylight.controller.config.yang.config.endpoint_provider</Export-Package>
+            <!-- <Bundle-Activator>
+              org.opendaylight.groupbasedpolicy.plugin.Activator
+            </Bundle-Activator> -->
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <sources>
+                <source>target/generated-sources/sal</source>
+                <source>target/generated-sources/config</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yang-maven-plugin</artifactId>
+        <dependencies>
+          <dependency>
+            <groupId>org.opendaylight.controller</groupId>
+            <artifactId>yang-jmx-generator-plugin</artifactId>
+            <version>0.2.5-SNAPSHOT</version>
+          </dependency>
+          <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>maven-sal-api-gen-plugin</artifactId>
+            <version>${yangtools.version}</version>
+            <type>jar</type>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <goals>
+              <goal>generate-sources</goal>
+            </goals>
+            <configuration>
+              <codeGenerators>
+                <generator>
+                  <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+                  <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                  <additionalConfiguration>
+                    <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+                  </additionalConfiguration>
+                </generator>
+                <generator>
+                  <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                  <outputBaseDir>${project.build.directory}/generated-sources/sal</outputBaseDir>
+                </generator>
+                <generator>
+                  <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
+                  <outputBaseDir>${project.build.directory}/site/models</outputBaseDir>
+                </generator>
+              </codeGenerators>
+              <inspectDependencies>true</inspectDependencies>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/endpoint_provider/impl/EndpointProviderModule.java b/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/endpoint_provider/impl/EndpointProviderModule.java
new file mode 100644 (file)
index 0000000..bab73a8
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+package org.opendaylight.controller.config.yang.config.endpoint_provider.impl;
+
+import org.opendaylight.groupbasedpolicy.endpoint.EndpointRegistry;
+
+public class EndpointProviderModule extends org.opendaylight.controller.config.yang.config.endpoint_provider.impl.AbstractEndpointProviderModule {
+    public EndpointProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public EndpointProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.controller.config.yang.config.endpoint_provider.impl.EndpointProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        return new EndpointRegistry(getDataBrokerDependency(),
+                                    getRpcRegistryDependency());
+    }
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/endpoint_provider/impl/EndpointProviderModuleFactory.java b/groupbasedpolicy/src/main/java/org/opendaylight/controller/config/yang/config/endpoint_provider/impl/EndpointProviderModuleFactory.java
new file mode 100644 (file)
index 0000000..5df124e
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+* Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+*
+* This program and the accompanying materials are made available under the
+* terms of the Eclipse Public License v1.0 which accompanies this distribution,
+* and is available at http://www.eclipse.org/legal/epl-v10.html
+*/
+/*
+* Generated file
+*
+* Generated from: yang module name: endpoint-provider-impl yang module local name: endpoint-provider-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Apr 24 18:12:49 PDT 2014
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.controller.config.yang.config.endpoint_provider.impl;
+public class EndpointProviderModuleFactory extends org.opendaylight.controller.config.yang.config.endpoint_provider.impl.AbstractEndpointProviderModuleFactory {
+
+}
diff --git a/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/endpoint/EndpointRegistry.java b/groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/endpoint/EndpointRegistry.java
new file mode 100644 (file)
index 0000000..e64b2f4
--- /dev/null
@@ -0,0 +1,168 @@
+package org.opendaylight.groupbasedpolicy.endpoint;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.common.util.RpcErrors;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointsL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.UnregisterEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.l3.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.l3.EndpointL3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.l3.EndpointL3Key;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorSeverity;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.Futures;
+
+/**
+ * Endpoint registry provides a scalable store for accessing and 
+ * updating information about endpoints.
+ * @author readams
+ */
+public class EndpointRegistry implements AutoCloseable, EndpointService {
+    private static final Logger LOG = LoggerFactory.getLogger(EndpointRegistry.class);
+
+    private final DataBrokerService dataProvider;
+    private final static String APPLICATION_TAG = 
+            "groupbasedpolicy:endpoint-registry";
+    
+    final BindingAwareBroker.RpcRegistration<EndpointService> rpcRegistration;
+
+    public EndpointRegistry(DataBrokerService dataProvider,
+                            RpcProviderRegistry rpcRegistry) {
+        super();
+        this.dataProvider = dataProvider;
+
+        rpcRegistration =
+                rpcRegistry.addRpcImplementation(EndpointService.class, this);
+
+        LOG.info("Created endpoint registry");
+    }
+
+    @Override
+    public void close() throws Exception {
+        rpcRegistration.close();
+    }
+
+    private void docommit(DataModificationTransaction t,
+                          String objecttag, String action,
+                          Collection<RpcError> errors) {
+
+        try {
+            RpcResult<TransactionStatus> commitresult = t.commit().get();
+            if (!commitresult.isSuccessful()) {
+                errors.addAll(commitresult.getErrors());
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            RpcError error = 
+                    RpcErrors.getRpcError(APPLICATION_TAG, 
+                                          objecttag, "commit error",
+                                          ErrorSeverity.ERROR,
+                                          "Could not " + action + " "
+                                          + objecttag, 
+                                          ErrorType.RPC, e);
+            errors.add(error);
+        }
+    }
+    
+    @Override
+    public Future<RpcResult<Void>>
+        registerEndpoint(RegisterEndpointInput input) {
+        Endpoint ep = new EndpointBuilder(input).build();
+        EndpointKey key = 
+                new EndpointKey(ep.getL2Namespace(), ep.getMacAddress());
+        InstanceIdentifier<Endpoint> iid = 
+                InstanceIdentifier.builder(Endpoints.class)
+                    .child(Endpoint.class, key).build();
+        DataModificationTransaction t = dataProvider.beginTransaction();
+        t.putOperationalData(iid, ep);
+        Collection<RpcError> errors = new ArrayList<>();
+        
+        docommit(t, iid.toString(), "register", errors);
+        
+        if (input.getL3Address() != null) {
+            for (L3Address l3addr : input.getL3Address()) {
+                t = dataProvider.beginTransaction();
+                EndpointL3Key key3 = new EndpointL3Key(l3addr.getIpAddress(), 
+                                                       l3addr.getL3Namespace());
+                EndpointL3 ep3 = new EndpointL3Builder(input)
+                    .setIpAddress(key3.getIpAddress())
+                    .setL3Namespace(l3addr.getL3Namespace())
+                    .build();
+                InstanceIdentifier<EndpointL3> iid_l3 = 
+                        InstanceIdentifier.builder(EndpointsL3.class)
+                            .child(EndpointL3.class, key3).build();
+                t.putOperationalData(iid_l3, ep3);
+                
+                docommit(t, iid_l3.toString(), "register", errors);
+            }
+        }
+        
+        RpcResult<Void> result = Rpcs.<Void>getRpcResult(errors.isEmpty(), 
+                                                         errors);
+        return Futures.immediateFuture(result);
+    }
+
+    @Override
+    public Future<RpcResult<Void>>
+        unregisterEndpoint(UnregisterEndpointInput input) {
+        EndpointKey key = 
+                new EndpointKey(input.getL2Namespace(), input.getMacAddress());
+        InstanceIdentifier<Endpoint> iid = 
+                InstanceIdentifier.builder(Endpoints.class)
+                    .child(Endpoint.class, key).build();
+        DataObject dao = dataProvider.readOperationalData(iid);
+
+        Collection<RpcError> errors = new ArrayList<>();
+        
+        if (dao != null && dao instanceof Endpoint) {
+            Endpoint ep = (Endpoint)dao;
+            
+            if (ep.getL3Address() != null) {
+                for (L3Address l3addr : ep.getL3Address()) {
+                    EndpointL3Key key3 = 
+                            new EndpointL3Key(l3addr.getIpAddress(), 
+                                              l3addr.getL3Namespace());
+                    InstanceIdentifier<EndpointL3> iid_l3 = 
+                            InstanceIdentifier.builder(EndpointsL3.class)
+                                .child(EndpointL3.class, key3).build();
+                    DataModificationTransaction t =
+                            dataProvider.beginTransaction();
+                    t.removeOperationalData(iid_l3);
+                    docommit(t, iid_l3.toString(), "unregister", errors);
+                }
+            }
+            
+            DataModificationTransaction t =
+                    dataProvider.beginTransaction();
+            t.removeOperationalData(iid);
+            docommit(t, iid.toString(), "unregister", errors);
+        }
+
+        // note that deleting an object that doesn't exist is fine.
+        RpcResult<Void> result = Rpcs.<Void>getRpcResult(errors.isEmpty(), 
+                                                         errors);
+        return Futures.immediateFuture(result);
+    }
+}
diff --git a/groupbasedpolicy/src/main/yang/common.yang b/groupbasedpolicy/src/main/yang/common.yang
new file mode 100644 (file)
index 0000000..08bfea2
--- /dev/null
@@ -0,0 +1,230 @@
+module gbp-common {
+    yang-version 1;
+
+    namespace "urn:opendaylight:groupbasedpolicy:common";
+    prefix "gbp-common";
+
+    import ietf-yang-types {
+        prefix yang;
+        revision-date 2010-09-24;
+    }   
+
+    description 
+        "Common types and definitions for group-based policy models";
+
+    revision "2014-04-21" {
+        description "Initial revision";
+    }
+
+    // **********
+    // Base types
+    // **********
+
+    typedef description {
+        description "A human-readable description for a object.";
+        type string {
+            length "1..4096";
+        }
+    }
+
+    typedef name {
+        description 
+            "A generic string name type. 
+             Must start with a letter";
+        type string {
+            pattern '[a-zA-Z]([a-zA-Z0-9\-_])*';
+            length "1..256";
+        }
+    }
+
+    // This is copied from ietf-yang-types@2013-07-15.  Should be removed
+    // when/if that's updated in yangtools
+    typedef uuid {
+      type string {
+        pattern
+          '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
+      }
+      description
+        "A Universally Unique IDentifier in the string representation
+      defined in RFC 4122.  The canonical representation uses
+      lowercase characters.
+
+      The following is an example of a UUID in string representation:
+      f81d4fae-7dec-11d0-a765-00a0c91e6bf6
+      ";
+      reference
+        "RFC 4122: A Universally Unique IDentifier (UUID) URN
+                 Namespace";
+
+    }
+
+    typedef unique-id {
+        type uuid;
+        description "A globally unique identifier";
+    }
+
+    // *************
+    // Relator names
+    // *************
+
+    typedef relator-name {
+        type name;
+        description "A name for a relator.";
+    }
+
+    typedef target-name {
+        type relator-name;
+        description "A name for a target.";
+    }
+
+    typedef named-selector-name {
+        type relator-name;
+        description "A name for a named selector.";
+    }
+
+    typedef target-selector-name {
+        type relator-name;
+        description "A name for a target selector.";
+    }
+
+    // *****************
+    // Unique object IDs
+    // *****************
+
+    typedef l2-namespace-id {
+        type unique-id;
+        description "An unique ID for a layer 2 namespace";
+    }
+
+    typedef l3-namespace-id {
+        type unique-id;
+        description "A unique ID for a layer 3 namespace";
+    }
+
+    typedef tenant-id {
+        type unique-id;
+        description "A unique ID for a tenant";
+    }
+
+    typedef endpoint-group-id {
+        type unique-id;
+        description "A unique ID for an endpoint group";
+    }
+
+    typedef contract-id {
+        type unique-id;
+        description "A unique ID for a contract";
+    }
+
+    typedef matcher-id {
+        type unique-id;
+        description "A unique ID for a matcher";
+    }
+
+    typedef quality-matcher-id {
+        type matcher-id;
+        description "A unique ID for a quality matcher";
+    }
+
+    typedef requirement-matcher-id {
+        type matcher-id;
+        description "A unique ID for a  matcher";
+    }
+
+    typedef condition-matcher-id {
+        type matcher-id;
+        description "A unique ID for a condition matcher";
+    }
+
+    typedef capability-matcher-id {
+        type matcher-id;
+        description "A unique ID for a capability matcher";
+    }
+
+    // *************
+    // Label names
+    // *************
+
+    typedef label-name {
+       type name;
+       description "A name for a label";
+    }
+
+    typedef capability-name {
+       type label-name;
+       description "A name for a capability";
+    }
+
+    typedef requirement-name {
+       type label-name;
+       description "A name for a requirement";
+    }
+
+    typedef quality-name {
+        type label-name;
+        description "A name for a quality.";
+    }
+
+    typedef condition-name {
+        type label-name;
+        description "A name for a condition.";
+    }
+
+    // ****************************
+    // Subject/clause-related names
+    // ****************************
+
+    typedef clause-name {
+        type name;
+        description "A name for a clause.";
+    }
+
+    typedef subject-name {
+        type name;
+        description "A name for a subject.";
+    }
+
+    typedef rule-name {
+        type name;
+        description "A name for a rule.";
+    }
+
+    // ********************
+    // Parameterized values
+    // ********************
+
+    typedef parameterized-id {
+        type unique-id;
+        description "A unique ID for a parameterized object";
+    }
+
+    typedef classifier-id {
+        type parameterized-id;
+        description "A unique ID for a classifier.";
+    }
+
+    typedef action-id {
+        type parameterized-id;
+        description "A unique ID for an action.";
+    }
+
+    typedef parameterized-name {
+        type name;
+        description "A name for a parameterized object";
+    }
+
+    typedef classifier-name {
+        type parameterized-name;
+        description "A name for a classifier.";
+    }
+
+    typedef action-name {
+        type parameterized-name;
+        description "A name for an action.";
+    }
+
+    typedef parameter-name {
+        type name;
+        description "A name for a parameter.";
+    }
+}
\ No newline at end of file
diff --git a/groupbasedpolicy/src/main/yang/endpoint-provider-impl.yang b/groupbasedpolicy/src/main/yang/endpoint-provider-impl.yang
new file mode 100644 (file)
index 0000000..fe382a7
--- /dev/null
@@ -0,0 +1,51 @@
+module endpoint-provider-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config:endpoint-provider:impl";
+
+    prefix "endpoint-provider-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+
+    description
+        "This module contains the base YANG definitions for 
+         endpoint-provider impl implementation.";
+
+    revision "2014-04-21" {
+        description
+            "Initial revision.";
+    }
+
+    // This is the definition of a service implementation
+    identity endpoint-provider-impl {
+        base config:module-type;
+        config:java-name-prefix EndpointProvider;
+    }
+
+    //augments the configuration,  
+    augment "/config:modules/config:module/config:configuration" {
+        case endpoint-provider-impl {
+            when "/config:modules/config:module/config:type = 'endpoint-provider-impl'";
+    
+            //wires in the data-broker service 
+            container data-broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory false;
+                        config:required-identity mdsal:binding-data-broker;
+                    }
+                }
+            }
+    
+            //Wires dependent services into this class - in this case the RPC registry service
+            container rpc-registry {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity mdsal:binding-rpc-registry;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/groupbasedpolicy/src/main/yang/endpoint-provider.yang b/groupbasedpolicy/src/main/yang/endpoint-provider.yang
new file mode 100644 (file)
index 0000000..7aa1142
--- /dev/null
@@ -0,0 +1,21 @@
+module endpoint-provider {
+     yang-version 1;
+     namespace "urn:opendaylight:params:xml:ns:yang:controller:config:endpoint-provider";
+     prefix "endpoint-provider";
+
+     import config { prefix config; revision-date 2013-04-05; }
+
+     description
+         "This module contains the base YANG definitions for 
+          endpoint-provider services.";
+
+     revision "2014-04-21" {
+         description
+             "Initial revision.";
+     }
+
+     identity toaster-provider {
+        base "config:service-type";
+        config:java-class "org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.EndpointData";
+    }
+ }
diff --git a/groupbasedpolicy/src/main/yang/endpoint.yang b/groupbasedpolicy/src/main/yang/endpoint.yang
new file mode 100644 (file)
index 0000000..8b9f963
--- /dev/null
@@ -0,0 +1,142 @@
+module endpoint {
+    yang-version 1;
+
+    namespace "urn:opendaylight:groupbasedpolicy:endpoint";
+    prefix "gbp-endpoint";
+
+    import gbp-common {prefix gbp-common;}
+    import ietf-inet-types {prefix inet;}
+    import ietf-yang-types {
+        prefix yang;
+        revision-date 2010-09-24;
+    } 
+
+    revision "2014-04-21" {
+        description
+            "Initial revision.";
+    }
+
+    // A base type for an end point
+    grouping endpoint-fields {
+        description "An endpoint and its associated metadata";
+        leaf tenant {
+            type gbp-common:tenant-id;
+            mandatory true;
+            description "The tenant with which this endpoint is associated";
+        }
+        leaf l2-namespace {
+            type gbp-common:l2-namespace-id;
+            mandatory true;
+            description 
+                "The namespace for the layer 2 address for this endpoint";
+        }
+        leaf mac-address {
+            type yang:mac-address;
+            mandatory true;
+            description 
+                "The MAC address for the endpoint";
+        }
+        list l3-address {
+            description
+                "All the layer 3 addresses associated with this endpoint";
+            key "l3-namespace ip-address";
+            leaf l3-namespace {
+                type gbp-common:l3-namespace-id;
+                mandatory true;
+                description 
+                    "The namespace for this layer 3 address";
+            }
+            leaf ip-address {
+                type inet:ip-address;
+                mandatory true;
+                description 
+                    "The actual IP address for the endpoint";
+            }
+            leaf ip-prefix {
+                type inet:ip-prefix;
+                description 
+                    "The subnet for this address";
+            }
+        }
+        leaf-list endpoint-group {
+            type gbp-common:endpoint-group-id;
+            description 
+                "The groups associated with this endpoint";
+        }
+        leaf-list condition {
+            type gbp-common:condition-name;
+            description 
+                "The conditions associated with this endpoint";
+        }
+        leaf timestamp {
+            type int64;
+            description
+                "The last timestamp associated with this endpoint record.  
+                 This will be used for aging data in the registry.";
+        }
+    }
+
+    container endpoints {
+        description 
+            "Endpoints indexed by layer 2 addreses.  When modifying data here,
+             you must also modify data in the endpoints-l3 container as well.";
+        list endpoint {
+            key "l2-namespace mac-address";
+            uses endpoint-fields;
+        }
+    }
+
+    container endpoints-l3 {
+        description 
+            "Endpoints indexed by layer 3 addreses.  When modifying data here,
+             you must also modify data in the endpoints container as well.";
+        list endpoint-l3 {
+            key "l3-namespace ip-address";
+
+            leaf l3-namespace {
+                type gbp-common:l3-namespace-id;
+                mandatory true;
+                description 
+                    "The namespace for this layer 3 address";
+            }
+            leaf ip-address {
+                type inet:ip-address;
+                mandatory true;
+                description 
+                    "The actual IP address for the endpoint";
+            }
+
+            uses endpoint-fields;
+        }
+    }
+
+    rpc register-endpoint {
+        description
+            "Register a new endpoint into the registry.  If there
+             is already an existing endpoint with the same keys, they 
+             will be overwritten with the new information.";
+
+        input {
+            uses endpoint-fields;
+        }
+    }
+
+    rpc unregister-endpoint {
+        description "Unregister an endpoint from the registry.";
+
+        input {
+            leaf l2-namespace {
+                type gbp-common:l2-namespace-id;
+                mandatory true;
+                description 
+                    "The namespace for the layer 2 address for this endpoint";
+            }
+            leaf mac-address {
+                type yang:mac-address;
+                mandatory true;
+                description 
+                    "The MAC address for the endpoint";
+            }
+        }
+    }
+}
diff --git a/groupbasedpolicy/src/main/yang/policy.yang b/groupbasedpolicy/src/main/yang/policy.yang
new file mode 100644 (file)
index 0000000..ba51381
--- /dev/null
@@ -0,0 +1,1045 @@
+module policy {
+    yang-version 1;
+
+    namespace "urn:opendaylight:groupbasedpolicy:policy";
+    prefix "gbp-policy";
+
+    import gbp-common {prefix gbp-common;}
+    import ietf-inet-types {prefix inet;}
+    import ietf-yang-types {
+        prefix yang;
+        revision-date 2010-09-24;
+    } 
+
+    include policy-contract;
+
+    description 
+        "This module defines the group-based policy configuration 
+         model.";
+
+    revision "2014-04-21" {
+        description
+            "Initial revision.";
+    }
+
+    // ***************
+    // Label groupings
+    // ***************
+
+    grouping label {
+        description
+            "Labels are used for matching contracts to endpoint groups 
+             through selectors and targets, as well as determining how
+             those contracts will be applied.  See more detailed
+             documentation for qualities, conditions, requirements,
+             and capabilities.";
+
+        leaf description {
+            description "A human-readable description for the label";
+            type gbp-common:description;
+        }
+        leaf inclusion-rule {
+            description "Specify how inheritance will work for this label";
+            default include;
+
+            type enumeration {
+                enum include {
+                    description 
+                        "This label will be included normally in the 
+                         matching.";
+                }
+                enum exclude {
+                    description 
+
+                        "This label will be excluded from the 
+                         matching.  This allows removing labels that
+                         would have otherwise been included because of
+                         inheritence rules.";
+                }
+            }
+        }
+    }
+
+    grouping quality-base {
+        description "Base type for qualities and matcher qualities.";
+        leaf name {
+            description "A user-visible name for the quality";
+            type gbp-common:quality-name;
+            mandatory true;
+        }
+        uses label;
+    }
+    
+    grouping has-qualities {
+        description "An object with a list of qualities";
+        list quality {
+            description 
+                "A quality is a label which selects which selects the 
+                 contracts that are in scope.  Another name for
+                 'quality' could be 'attribute' or 'characteristic.'
+                 Qualities can be scoped to either a specific contract
+                 or to a target within that contract.
+
+                 Contracts are matched to provider and consumer
+                 endpoint groups based on the selectors in those
+                 endpoint groups that match the quality.
+
+                 Qualities for a contract are inherited from the
+                 enclosing contract.
+
+                 Qualities for a target with a given name are
+                 inherited both from the enclosing parent contract and
+                 from any targets with the same name within the
+                 enclosing parent contract.";
+
+            key name;
+            uses quality-base;
+        }
+    }
+
+    grouping has-matcher-qualities {
+        description "An object with a list of matcher qualities";
+        list matcher-quality {
+            description 
+                "A matcher quality is a quality with a namespace field 
+                 used in quality matchers.  The name of the matcher
+                 quality matches against qualities in contract
+                 targets.";
+
+            key name;
+            uses quality-base;
+
+            leaf target-namespace {
+                description 
+                    "The namespace of the target to match.  This allows
+                     us to specify that we want to match only
+                     qualities scoped to a particular target name.
+                     This parameter is optional; if not specified,
+                     match against any target namespace.";
+                
+                type gbp-common:target-name;
+            }
+        }
+    }
+
+    grouping requirement-base {
+        description "Base type for requirements and matcher requirements.";
+        leaf name {
+            description "A user-visible name for the requirement";
+            type gbp-common:requirement-name;
+            mandatory true;
+        }
+        uses label;
+    }
+
+    grouping has-requirements {
+        list requirement {
+            description 
+                "A requirement is a label that, along with capabilities, 
+                 selects how contracts are applied by selecting the
+                 applicable subjects within that contract.
+                 Requirements represent the fact that an endpoint
+                 group requires that some specific functionality be
+                 provided to it in order to function.
+
+                 Requirements scoped to an endpoint group (as well as
+                 any parent endpoint groups) are inherited by all of
+                 that group's contract selectors.  Contract selectors
+                 also inherit requirements from any contract selectors
+                 in the parent groups that have with matching names.
+
+                 Note that requirements play no role in choosing which
+                 contracts apply; they only affect how the contracts
+                 that are chosen will be interpreted.";
+        
+            key name;
+            uses requirement-base;
+        }
+    }
+
+    grouping has-matcher-requirements {
+        description "An object with a list of matcher requirements";
+        list matcher-requirement {
+            description 
+                "A matcher requirement is a requirement with a namespace
+                 field used in requirement matchers.  The name of the
+                 matcher requirement matches against requirements in
+                 endpoint groups.";
+
+            key name;
+            uses requirement-base;
+
+            leaf selector-namespace {
+                description 
+                    "The namespace of the selector to match.  This allows
+                     us to specify that we want to match only
+                     requirements scoped to a particular selector name.
+                     This parameter is optional; if not specified,
+                     match against any selector namespace.";
+                
+                type gbp-common:target-name;
+            }
+        }
+    }
+
+    grouping capability-base {
+        description "Base type for capabilities and matcher capabilities.";
+        leaf name {
+            description "A user-visible name for the capability";
+            type gbp-common:capability-name;
+            mandatory true;
+        }
+        uses label;
+    }
+
+    grouping has-capabilities {
+        list capability {
+            description 
+                "A capability is a label that, along with requirements, 
+                 selects how contracts are applied by selecting the
+                 applicable subjects within that contract.
+                 Capabilities are specific pieces of functionality
+                 that can be exposed to other endpoint groups that may
+                 meet functional requirements of those endpoint
+                 groups.
+
+                 Capabilities scoped to an endpoint group (as well as
+                 any parent endpoint groups) are inherited by all of
+                 that group's contract selectors.  Contract selectors
+                 also inherit capabilities from any contract selectors
+                 in the parent groups that have matching names.
+
+                 Note that capabilities play no role in choosing which
+                 contracts apply; they only affect how the contracts
+                 that are chosen will be interpreted.";
+
+            key "name";
+            uses capability-base;
+        }
+    }
+
+    grouping has-matcher-capabilities {
+        description "An object with a list of matcher capabilities";
+        list matcher-capability {
+            description 
+                "A matcher capability is a capability with a namespace
+                 field used in capability matchers.  The name of the
+                 matcher capability matches against capabilities in
+                 endpoint groups.";
+
+            key name;
+            uses capability-base;
+
+            leaf selector-namespace {
+                description 
+                    "The namespace of the selector to match.  This allows
+                     us to specify that we want to match only
+                     capabilities scoped to a particular selector name.
+                     This parameter is optional; if not specified,
+                     match against any selector namespace.";
+                
+                type gbp-common:target-name;
+            }
+        }
+    }
+
+    grouping has-conditions {
+        list condition {
+            description 
+                "A condition is a state label for endpoints that can 
+                 change over time.  As conditions change for certain
+                 endpoints, this can affect which subjects are in
+                 scope as determined by how the clauses in the
+                 contract match against the requirements and
+                 capabilities for the endpoint group, and the
+                 conditions for the endpoints.";
+
+            key "name";
+            leaf name {
+                description "A user-visible name for the condition";
+                type gbp-common:condition-name;
+                mandatory true;
+            }
+            uses label;
+        }
+    }
+
+    grouping matcher {
+        description 
+            "A matcher allows matching against labels.  This is used 
+             to both to match contracts to endpoint groups by matching
+             on qualities, and then to match against subjects in the
+             contract by matching on requirements, capabilities, and
+             conditions.";
+
+        leaf match-type {
+            description 
+                "Specify how many of the labels must match";
+            default all;
+            type enumeration {
+                enum all {
+                    description 
+                        "All specified qualities must match.";
+                }
+                enum any {
+                    description 
+                        "At least one of the specified qualities 
+                         must match.";
+                }
+                enum none {
+                    description 
+                        "None of the specified qualities 
+                         can match.";
+                }
+            }
+        }
+    }
+
+    // ************************
+    // Endpoint group groupings
+    // ************************
+
+    grouping relator {
+        description 
+            "Relators allow contracts and endpoint groups to be related
+             to each other through a matching process.  See target,
+             selection-relator, target-selector, and named-selector
+             for more information.";
+    }
+
+    grouping selection-relator {
+        description 
+            "Selection relators allow endpoint groups to select 
+             contracts based on their name or on their qualities.";
+        uses relator;
+    }
+
+    grouping consumer-selection-relator {
+        description
+            "A selection relator for matching contracts to meet
+             endpoint group requirements.  See consumer-named-selector
+             and consumer-target-selector for more details.";
+
+        uses has-requirements;
+    }
+
+    grouping provider-selection-relator {
+        description
+            "A selection relator for matching contracts to meet
+             endpoint group requirements.  See provider-named-selector
+             and provider-named-selector for more details.";
+
+        uses has-capabilities;
+    }
+
+    grouping named-selector {
+        description
+            "A named selector selects a contract based on the name of
+             the contract.  Once the contract is selected, the
+             requirements and capabilities are used to select specific
+             subjects within that contract.  Named selectors are the
+             simplest way to select a contract.  If you need a more
+             advanced selector, see the target selector.
+
+             There are two kinds of named selector: consumer named
+             selectors and provider named selectors.  Consumer named
+             selectors select contracts to meet requirements for the
+             endpoint group, and provider named selectors select
+             contracts to provide capabilities for the endpoint group.";
+
+        uses selection-relator;
+
+        leaf name {
+            description "A name for the named selector.";
+            type gbp-common:named-selector-name;
+        }
+
+        leaf-list contract {
+            description "Specific contracts to select.";
+            type leafref {
+                path "/tenants/tenant/contract/id";
+            }
+        }
+    }
+
+    grouping target-selector {
+        description 
+            "Target selectors select contracts for the endpoint group.
+             First, the quality matchers are used to select the
+             contracts.  Then, the requirements and capabilities are
+             used to select specific subjects within that contract.
+             Target selectors are an advanced method for selecting
+             contracts; for a simpler method, see the named selector.
+
+             There are two kinds of target selectors: consumer target
+             selectors and provider target selectors.  Consumer target
+             selectors select contracts to meet requirements for the
+             endpoint group, and provider target selectors select
+             contracts to provide capabilities to other endpoint
+             groups.";
+
+        uses selection-relator;
+
+        leaf name {
+            description "A name for the target selector";
+            type gbp-common:target-selector-name;
+        }
+
+        list quality-matcher {
+            description 
+                "A quality matcher is used in a target selector to
+                 match against the qualities in a contract target.
+                 You can specify a list of qualities to match against.
+                 You can choose whether all qualities listed must
+                 match or if a match can be made with any of the
+                 qualities.";
+
+            key "id";
+            leaf id {
+                description "A unique ID for the quality matcher";
+                type gbp-common:quality-matcher-id;
+                mandatory true;
+            }
+
+            uses matcher;
+            uses has-matcher-qualities;
+        }
+    }
+
+    // ******************
+    // Contract groupings
+    // ******************
+
+    grouping has-direction {
+        description "An object that has a directionality.";
+        leaf direction {
+            default bidirectional;
+            type enumeration {
+                enum in {
+                    description 
+                    "Applies to traffic into provider endpoint group";
+                }
+                enum out {
+                    description 
+                    "Applies to traffic out of provider endpoint group";
+                }
+                enum bidirectional {
+                    description 
+                    "Applies to traffic in both directions";
+                }
+            }
+        }
+    }
+
+    grouping has-parameter-values {
+        list parameter-value {
+            key "name";
+            leaf name {
+                type gbp-common:parameter-name;
+            }
+            union value {
+                type string;
+                type int64;
+            }
+        }
+    }
+
+    grouping has-order {
+        leaf order {
+            description 
+                "Specify the ordering of an ordered list 
+                             of elements.";
+            type int32 {
+                range "0..max";
+            }
+        }
+    }
+
+    grouping has-classifier-refs {
+        description "Objects containing lists of classifier refs";
+        list classifier-ref {
+            description 
+                "A reference to classifier that is used to match traffic 
+                 traveling between the endpoint groups that form the
+                 contract.  Classifiers will generally have some set
+                 of parameters that must be filled in here for the
+                 specific use case.
+
+                 Classifiers can be found on clauses, subjects, and
+                 rules.  Rules inherit their classifiers from both
+                 their enclosing subject and clause.  Classifiers have
+                 meaning only when inherited by a rule.";
+
+            leaf id {
+                description "The ID of the classifier";
+                type leafref {
+                    path "/subject-features/classifier/id";
+                }
+            }
+
+            leaf connection-tracking {
+                description 
+                    "Set up connection tracking for this classifier, 
+                     which allows the traffic in the reverse direction
+                     as connections are established.  This enables 
+                     rules that allow connections be be initiated only 
+                     from one side, but once initiated the two sides 
+                     can communicate for that connection.";
+
+                default normal;
+                type enumeration {
+                    enum normal {
+                        description 
+                            "Match only traffic matching the classifier 
+                             strictly";
+                    }
+                    enum reflexive {
+                        description 
+                            "Additionally match reverse traffic for 
+                             connections";
+                    }
+                }
+            }
+
+            uses has-direction;
+            uses has-parameter-values;
+        }
+    }
+
+    grouping has-action-refs {
+        description "Objects containing lists of action refs";
+        list action-ref {
+            description 
+                "A reference to an action defined in the subject 
+                 features.  Actions will generally have some set of
+                 parameters that must be filled in here for the
+                 specific use case.
+
+                 Actions can be found on clauses, subjects, and rules.
+                 Rules inherit their actions from both their enclosing
+                 subject and clause.  Actions have meaning only when
+                 inherited by a rule.";
+
+            leaf id {
+                description "The ID of the action";
+                type leafref {
+                    path "/subject-features/action/id";
+                }
+            }
+            uses has-direction;
+            uses has-parameter-values;
+            uses has-order;
+        }
+    }
+
+    grouping has-subjects {
+        description "Objects containing lists of subjects";
+        list subject {
+            description
+                "Subjects define rules to allow traffic to flow between 
+                 endpoints in different endpoint groups.  No
+                 communication is allowed unless a subject allows that
+                 communication.
+
+                 After a contract has been selected, clauses in that
+                 contract match against the requirements,
+                 capabilities, and conditions that apply to the
+                 endpoints or endpoint groups that are participating
+                 in the contract.  Clauses that match contain subjects
+                 which then become active.  Subjects can be present in
+                 the contract, or in the clause.  Subjects defined in
+                 the contract will apply to all clauses.
+
+                 An active subject can then apply its rules.  Rules
+                 match against the traffic using classifiers, and then
+                 apply actions to the traffic for matching rules.
+                 Only the first matching rule will apply.
+
+                 Rules are applied in order according to their order
+                 parameter.  Rules defined in a subject with a more
+                 specific scope are applied before any rules defined
+                 subjects in an enclosing scope.
+
+                 XXX TODO - what order do we apply rules for subjects
+                 with the same scope?";
+
+            leaf name {
+                description "A name for the subject";
+                type gbp-common:subject-name;
+            }
+                
+            uses has-classifier-refs;
+            uses has-action-refs;
+
+            list rule {
+                description 
+                    "A rule is applied to traffic between endpoints 
+                     in different endpoint groups.  Rules match
+                     against the traffic using classifiers, and then
+                     apply actions to the traffic for matching rules.
+                     Only the first matching rule will apply.";
+
+                key "name";
+                leaf name {
+                    type gbp-common:rule-name;
+                }
+
+                uses has-classifier-refs;
+                uses has-action-refs;
+                uses has-order;
+            }
+        }
+    }
+
+    // XXX - perhaps we can express this instead by having 
+    // modules extend/augment classifiers and actions?
+    grouping has-parameters {
+        description "A parameterized object";
+
+        leaf description {
+            description "A user-readable description";
+            type gbp-common:description;
+        }
+
+        list parameters {
+            description 
+                "A parameter for the classifier that can be 
+                 passed in.";
+            key "name";
+            leaf name {
+                description "A user-visible name for the parameter";
+                type gbp-common:parameter-name;
+            }
+            leaf description {
+                description 
+                    "A user-visible description of the meaning of 
+                     the parameter.";
+                type gbp-common:description;
+            }
+            leaf type {
+                description "The type of the parameter";
+                default string;
+                type enumeration {
+                    enum string {
+                        description "A string-valued parameter";
+                    }
+                    enum int {
+                        description "An integer-valued parameter";
+                    }
+                }
+            }
+            leaf required {
+                description "Specify whether the parameter is
+                                     required for correct operation.";
+                default optional;
+                type enumeration {
+                    enum required {
+                        description "The parameter is required";
+                    }
+                    enum optional {
+                        description "The parameter is optional";
+                    }
+                }
+            }
+        }
+    }
+
+    container subject-features {
+        description
+            "Contains configuration for the set of actions and
+             classifiers that can be defined for a subject.  This will
+             be specific to the capabilities of the underlying
+             renderer.";
+
+        list classifier {
+            description
+                "A classifier is used to match traffic traveling between 
+                 the endpoint groups that form the contract.
+                 Classifiers can define parameters that will need to
+                 be filled in when a particular rule references it.";
+
+            key "id";
+            uses has-parameters;
+
+            leaf id {
+                description "A unique ID for the classifier";
+                type gbp-common:classifier-id;
+            }
+
+            leaf name {
+                description "A user-visible name for the classifier";
+                type gbp-common:classifier-name;
+            }
+        }
+
+        list action {
+            description
+                "A action to be applied to traffic across endpoint 
+                 groups.";
+
+            key "id";
+            uses has-parameters;
+
+            leaf id {
+                description "A unique ID for the action";
+                type gbp-common:action-id;
+            }
+
+            leaf name {
+                description "A user-visible name for the action";
+                type gbp-common:action-name;
+            }
+        }
+    }
+
+    // *******
+    // Tenants
+    // *******
+
+    container tenants {
+        description "The list of all known tenants";
+
+        list tenant {
+            description "";
+
+            key "id";
+            leaf id {
+                description "A unique ID for the tenant";
+                mandatory true;
+                type gbp-common:tenant-id;
+            }
+            leaf name {
+                description "A user-visible name for the tenant";
+                type gbp-common:name;
+            }
+            leaf description {
+                description "A user-readable description for the tenant";
+                type gbp-common:description;
+            }
+            leaf-list parent {
+                description "Parent tenant from which we inherit"; 
+                
+                type leafref {
+                    path "/tenants/tenant/id";
+                }
+            } 
+
+            // ***************
+            // Endpoint groups
+            // ***************
+
+            list endpoint-group {
+                description
+                    "Endpoint groups are sets of endpoints that share a 
+                     common set of policies.  Endpoint groups are
+                     matched to contracts using selectors, contracts
+                     determine which endpoints can communicate and in
+                     what way.
+                     
+                     Endpoint groups have both requirements and
+                     capabilities, which represent specific pieces of
+                     functionality that are exposed at the boundary of
+                     those groups.  Requirements represent some
+                     specific functionality that is needed for the
+                     endpoints in the endpoint group to function.
+                     Correspondingly, capabilities are pieces of
+                     functionality that the endpoints in the endpoint
+                     group can provide to other endpoints.
+                     
+                     Contracts can be selected through either a named
+                     selector, which matches specific contracts by
+                     name, or by a target selector which will match
+                     contracts by matching its list of qualities to
+                     the list of qualities for a target on the
+                     contract.  The contract selectors choose which
+                     contracts are in scope.  Note that requirements
+                     and capabilities are not used when choosing which
+                     contracts are in scope; these are used to
+                     determine how a contract will be interpreted.
+                     
+                     There are two broad category of selectors:
+                     provider selectors and consumer selectors.  The
+                     provider selectors allow selecting contracts that
+                     allow the endpoint group to expose its
+                     capabilities.  The consumer selectors allow
+                     selecting contracts which allow the endpoint
+                     group to meet its requirements.";
+
+                key "id";
+            
+                leaf id {
+                    mandatory true;
+                    type gbp-common:endpoint-group-id;
+                }
+
+                leaf description {
+                    description 
+                        "A human-readable description for the endpoint
+                         group.";
+                    type gbp-common:description;
+                }
+                uses has-requirements;
+                uses has-capabilities;
+
+                list consumer-named-selector {
+                    description
+                        "Consumer named selectors are named selectors 
+                         that select contracts to meet the
+                         requirements of the endpoint group.
+                         
+                         The consumer named selector selects a
+                         contract based on the name of the contract.
+                         Once the contract is selected, the
+                         requirements are used to select specific
+                         subjects within that contract.";
+
+                    key "name";
+                    uses named-selector;
+                    uses consumer-selection-relator;
+                }
+
+                list provider-named-selector {
+                    description 
+                        "Provider named selectors are named selectors 
+                         that select contracts to provide capabilties
+                         to other endpoint group.
+                         
+                         The provider named selector selects a
+                         contract based on the name of the contract.
+                         Once the contract is selected, the capabilies
+                         are used to select specific subjects within
+                         that contract.";
+
+                    key "name";
+                    uses named-selector;
+                    uses provider-selection-relator;
+                }
+
+                list consumer-target-selector {
+                    description 
+                        "Consumer target selectors are target selectors 
+                         that select contracts to meet the requirements 
+                         of the endpoint group.
+                         
+                         The consumer target selector selects a
+                         contract using the quality matchers to match
+                         against the qualities specified on the
+                         contract targets.  Once the contract is
+                         selected, the requirements are used to select
+                         specific subjects within that contract.";
+
+                    key "name";
+                    uses target-selector;
+                    uses consumer-selection-relator;
+                }
+
+                list provider-target-selector {
+                    description
+                        "Provider target selectors are target selectors 
+                         that select contracts to provide capabilties
+                         to other endpoint group.
+                         
+                         The provider target selector selects a
+                         contract using the quality matchers to match
+                         against the qualities specified on the
+                         contract targets.  Once the contract is
+                         selected, the capabilities are used to select
+                         specific subjects within that contract.";
+
+                    key "name";
+                    uses target-selector;
+                    uses provider-selection-relator;
+                }
+
+                leaf parent {
+                    description 
+                        "Parent endpoint group from which we inherit"; 
+
+                    type leafref {
+                        path "/tenants/tenant/endpoint-group/id";
+                    }
+                }
+            }
+
+            // *********
+            // Contracts
+            // *********
+
+            list contract {
+                description
+                    "Contracts contain a set of subjects that describe
+                     the communication allowed between endpoints in
+                     endpoint groups.  Contracts are matched to endpoint
+                     groups by selectors.";
+                
+                key "id";
+                leaf id {
+                    description "A unique ID for the contract";
+                    type gbp-common:contract-id;
+                    mandatory true;
+                }
+                
+                leaf description {
+                    description 
+                        "A human-readable description for the contract.";
+                    type gbp-common:description;
+                }
+                                
+                // *******
+                // Relator
+                // *******
+                
+                uses has-qualities;
+                
+                list target {
+                    description 
+                        "Targets on a contract allow grouping sets of qualities
+                         together, as well as providing a namespace for
+                         the qualities that are matched.";
+                
+                    key "name";
+                    leaf name {
+                        description 
+                            "The name for this target.  This can also be used 
+                             by quality matchers as a namespace for qualities.";
+                        type gbp-common:target-name;
+                        mandatory true;
+                    }
+                
+                    uses relator;
+                    uses has-qualities;
+                }
+                
+                // ********************
+                // Clauses and subjects
+                // ********************
+                
+                uses has-subjects;
+                
+                list clause {
+                    description 
+                        "Clauses are used to determine which subjects are 
+                         active once a contract is selected using the
+                         contract selectors.
+                
+                         Clauses are activated by matching against
+                         requirements on the consumer endpoint group,
+                         capabilities on the provider endpoint group, and
+                         conditions on the individual endpoints in the
+                         endpoint group.";
+                
+                    key "name";
+                    leaf name {
+                        type gbp-common:clause-name;
+                    }
+                
+                    // ********
+                    // Matchers
+                    // ********
+                
+                    container consumer-matchers {
+                        description 
+                            "Matchers that apply to the consumer endpoint group.";
+                        list requirement-matcher {
+                            description 
+                                "Match against requirements in the consumer 
+                                 endpoint group.";
+                
+                            key "id";
+                            leaf id {
+                                description 
+                                    "A unique ID for the requirement matcher";
+                                type gbp-common:requirement-matcher-id;
+                                mandatory true;
+                            }
+                
+                            uses matcher;
+                            uses has-matcher-requirements;
+                        }
+                
+                        list consumer-condition-matcher {
+                            description 
+                                "Match against conditions on endpoints in the 
+                                 consumer endpoint group.";
+                
+                            key "id";
+                            leaf id {
+                                description 
+                                    "A unique ID for the condition matcher";
+                                type gbp-common:condition-matcher-id;
+                                mandatory true;
+                            }
+                
+                            uses matcher;
+                            uses has-conditions;
+                        }
+                    }
+                
+                    container provider-matchers {
+                        description 
+                            "Matchers that apply to the provider endpoint group";
+                
+                        list capability-matcher {
+                            description 
+                                "Match against capabilities in the provider  
+                                 endpoint group.";
+                
+                            key "id";
+                            leaf id {
+                                description 
+                                    "A unique ID for the capability matcher";
+                                type gbp-common:capability-matcher-id;
+                                mandatory true;
+                            }
+                
+                            uses matcher;
+                            uses has-matcher-capabilities;
+                        }
+                
+                        list provider-condition-matcher {
+                            description 
+                                "Match against conditions on endpoints in the 
+                                 provider endpoint group.";
+                
+                            key "id";
+                            leaf id {
+                                description 
+                                    "A unique ID for the condition matcher";
+                                type gbp-common:condition-matcher-id;
+                                mandatory true;
+                            }
+                
+                            uses matcher;
+                            uses has-conditions;
+                        }
+                    }
+                
+                    // ****************************
+                    // Classifiers/actions/subjects
+                    // ****************************
+                
+                    uses has-classifier-refs;
+                    uses has-action-refs;
+                    uses has-subjects;
+                }
+                
+                // ***********
+                // Inheritance
+                // ***********
+                
+                leaf-list parent {
+                    description "Parent contract from which we inherit"; 
+                
+                    type leafref {
+                        path "/tenants/tenant/contract/id";
+                    }
+                } 
+            }
+        }
+    }
+
+    // XXX - TODO - Contracts spanning multiple tenants
+    // XXX - TODO - model forwarding model
+    // XXX - TODO - model scoring
+    // XXX - TODO - model circumstances
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644 (file)
index 0000000..789f267
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.groupbasedpolicy</groupId>
+    <artifactId>commons.groupbasedpolicy</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+    <relativePath>commons/parent</relativePath>
+  </parent>
+  <groupId>org.opendaylight.groupbasedpolicy</groupId>
+  <artifactId>groupbasedpolicy.project</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <packaging>pom</packaging>
+  <prerequisites>
+    <maven>3.0</maven>
+  </prerequisites>
+  <modules>
+    <module>commons/parent</module>
+    <module>groupbasedpolicy</module>
+  </modules>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>${checkstyle.version}</version>
+        <configuration>
+          <!-- checkstyle is evil -->
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/groupbasedpolicy.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/groupbasedpolicy.git</developerConnection>
+    <tag>HEAD</tag>
+    <url>https://wiki.opendaylight.org/view/Group_Policy:Main</url>
+  </scm>
+
+</project>