Provision flows on OLT and fabric when we add a vOLT tenant

Change-Id: I22a73c6c2c472155408ba109f0d21b5907107857
diff --git a/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXOSIntegrationManager.java b/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXOSIntegrationManager.java
index 9950c33..dccbd4e 100644
--- a/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXOSIntegrationManager.java
+++ b/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXOSIntegrationManager.java
@@ -15,11 +15,12 @@
  */
 package org.onosproject.xosintegration;
 
-import java.util.Dictionary;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
-
+import com.eclipsesource.json.JsonArray;
+import com.eclipsesource.json.JsonObject;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -28,19 +29,28 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.VlanId;
 import org.onlab.util.Tools;
 import org.onosproject.cfg.ComponentConfigService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 
-import com.eclipsesource.json.JsonArray;
-import com.eclipsesource.json.JsonObject;
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.WebResource;
-import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+import java.util.Dictionary;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static com.google.common.net.MediaType.JSON_UTF_8;
@@ -68,12 +78,26 @@
     private static final String XOS_TENANT_BASE_URI = "/xoslib/volttenant/";
     private static final int TEST_XOS_PROVIDER_SERVICE = 1;
 
+    private static final DeviceId FABRIC_DEVICE_ID = DeviceId.deviceId("of:5e3e486e73000187");
+    private static final PortNumber FABRIC_OLT_CONNECT_POINT = PortNumber.portNumber(2);
+    private static final PortNumber FABRIC_VCPE_CONNECT_POINT = PortNumber.portNumber(3);
+    private static final String FABRIC_CONTROLLER_ADDRESS = "10.0.3.136";
+    private static final int FABRIC_SERVER_PORT = 8181;
+    private static final String FABRIC_BASE_URI = "/onos/cordfabric/vlans/add";
+
+    private static final ConnectPoint FABRIC_PORT = new ConnectPoint(
+            DeviceId.deviceId("of:000090e2ba82f974"),
+            PortNumber.portNumber(2));
+
     private final Logger log = getLogger(getClass());
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected CoreService coreService;
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ComponentConfigService cfgService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected FlowObjectiveService flowObjectiveService;
+
     @Property(name = XOS_SERVER_ADDRESS_PROPERTY_NAME,
               value = TEST_XOS_SERVER_ADDRESS,
               label = "XOS Server address")
@@ -267,9 +291,16 @@
                 .withProviderService(providerServiceId)
                 .withServiceSpecificId(newTenant.serviceSpecificId())
                 .withVlanId(newTenant.vlanId())
+                .withPort(newTenant.port())
                 .build();
         String json = tenantToJson(tenantToCreate);
+
+        provisionDataPlane(tenantToCreate);
+
         postRest(json);
+
+        provisionFabric(VlanId.vlanId(Short.parseShort(newTenant.vlanId())));
+
         return newTenant;
     }
 
@@ -284,6 +315,72 @@
         }
     }
 
+    private void provisionDataPlane(VoltTenant tenant) {
+        VlanId vlan = VlanId.vlanId(Short.parseShort(tenant.vlanId()));
+
+        TrafficSelector fromGateway = DefaultTrafficSelector.builder()
+                .matchInPhyPort(tenant.port().port())
+                .build();
+
+        TrafficSelector fromFabric = DefaultTrafficSelector.builder()
+                .matchInPhyPort(FABRIC_PORT.port())
+                .matchVlanId(vlan)
+                .build();
+
+        TrafficTreatment toFabric = DefaultTrafficTreatment.builder()
+                .pushVlan()
+                .setVlanId(vlan)
+                .setOutput(FABRIC_PORT.port())
+                .build();
+
+        TrafficTreatment toGateway = DefaultTrafficTreatment.builder()
+                .popVlan()
+                .setOutput(tenant.port().port())
+                .build();
+
+        ForwardingObjective forwardToFabric = DefaultForwardingObjective.builder()
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .withPriority(1000)
+                .makePermanent()
+                .fromApp(appId)
+                .withSelector(fromGateway)
+                .withTreatment(toFabric)
+                .add();
+
+        ForwardingObjective forwardToGateway = DefaultForwardingObjective.builder()
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .withPriority(1000)
+                .makePermanent()
+                .fromApp(appId)
+                .withSelector(fromFabric)
+                .withTreatment(toGateway)
+                .add();
+
+        flowObjectiveService.forward(FABRIC_PORT.deviceId(), forwardToFabric);
+        flowObjectiveService.forward(FABRIC_PORT.deviceId(), forwardToGateway);
+    }
+
+    private void provisionFabric(VlanId vlanId) {
+        String json = "{\"vlan\":" + vlanId + ",\"ports\":[";
+        json += "{\"device\":\"" + FABRIC_DEVICE_ID.toString() + "\",\"port\":\""
+                + FABRIC_OLT_CONNECT_POINT.toString() + "\"},";
+        json += "{\"device\":\"" + FABRIC_DEVICE_ID.toString() + "\",\"port\":\""
+                + FABRIC_VCPE_CONNECT_POINT.toString() + "\"}";
+        json += "]}";
+
+        String baseUrl = "http://" + FABRIC_CONTROLLER_ADDRESS + ":"
+                + Integer.toString(FABRIC_SERVER_PORT);
+        Client client = Client.create();
+        client.addFilter(new HTTPBasicAuthFilter("padmin@vicci.org", "letmein"));
+        WebResource resource = client.resource(baseUrl
+                                                       + FABRIC_BASE_URI);
+        WebResource.Builder builder = resource.accept(JSON_UTF_8.toString())
+                .type(JSON_UTF_8.toString());
+
+        ClientResponse response = builder.post(ClientResponse.class, json);
+
+    }
+
     /**
      * Extracts properties from the component configuration context.
      *
diff --git a/apps/xos-integration/src/main/java/org/onosproject/xosintegration/VoltTenant.java b/apps/xos-integration/src/main/java/org/onosproject/xosintegration/VoltTenant.java
index 18b24e1..6685b7a 100644
--- a/apps/xos-integration/src/main/java/org/onosproject/xosintegration/VoltTenant.java
+++ b/apps/xos-integration/src/main/java/org/onosproject/xosintegration/VoltTenant.java
@@ -16,6 +16,7 @@
 package org.onosproject.xosintegration;
 
 import com.google.common.base.MoreObjects;
+import org.onosproject.net.ConnectPoint;
 
 public final class VoltTenant {
 
@@ -24,6 +25,7 @@
     private final long providerService;
     private final String serviceSpecificId;
     private final String vlanId;
+    private final ConnectPoint port;
 
     /**
      * Constructs a vOLT tenant object.
@@ -35,12 +37,13 @@
      * @param vlanId vlan id for the user
      */
     private VoltTenant(String humanReadableName, long id, long providerService,
-                       String serviceSpecificId, String vlanId) {
+                       String serviceSpecificId, String vlanId, ConnectPoint port) {
         this.humanReadableName = humanReadableName;
         this.id = id;
         this.providerService = providerService;
         this.serviceSpecificId = serviceSpecificId;
         this.vlanId = vlanId;
+        this.port = port;
     }
 
     /**
@@ -97,6 +100,10 @@
         return vlanId;
     }
 
+    public ConnectPoint port() {
+        return port;
+    }
+
     /**
      * Builder class to allow callers to assemble tenants.
      */
@@ -107,6 +114,7 @@
         private long providerService = -1;
         private String serviceSpecificId = "unknown";
         private String vlanId = "unknown";
+        private ConnectPoint port;
 
         /**
          * Sets the name string for the tenant.
@@ -163,6 +171,11 @@
             return this;
         }
 
+        public Builder withPort(ConnectPoint port) {
+            this.port = port;
+            return this;
+        }
+
         /**
          * Constructs a VoltTenant from the assembled data.
          *
@@ -170,7 +183,7 @@
          */
         public VoltTenant build() {
             return new VoltTenant(humanReadableName, id, providerService,
-                    serviceSpecificId, vlanId);
+                    serviceSpecificId, vlanId, port);
         }
     }
 
@@ -182,6 +195,7 @@
                 .add("providerService", providerService())
                 .add("serviceSpecificId", serviceSpecificId())
                 .add("vlanId", vlanId())
+                .add("port", port())
                 .toString();
     }
 
diff --git a/apps/xos-integration/src/main/java/org/onosproject/xosintegration/cli/VoltTenantsCreateCommand.java b/apps/xos-integration/src/main/java/org/onosproject/xosintegration/cli/VoltTenantsCreateCommand.java
index 611446d..3a5b094 100644
--- a/apps/xos-integration/src/main/java/org/onosproject/xosintegration/cli/VoltTenantsCreateCommand.java
+++ b/apps/xos-integration/src/main/java/org/onosproject/xosintegration/cli/VoltTenantsCreateCommand.java
@@ -18,6 +18,7 @@
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
 import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
 import org.onosproject.xosintegration.VoltTenant;
 import org.onosproject.xosintegration.VoltTenantService;
 
@@ -38,6 +39,11 @@
             required = true, multiValued = false)
     String vlanId;
 
+    @Argument(index = 2, name = "port",
+            description = "Port",
+            required = true, multiValued = false)
+    String port;
+
     @Override
     protected void execute() {
         VoltTenantService service = get(VoltTenantService.class);
@@ -45,7 +51,9 @@
         VoltTenant newTenant = VoltTenant.builder()
                 .withServiceSpecificId(serviceSpecificId)
                 .withVlanId(vlanId)
+                .withPort(ConnectPoint.deviceConnectPoint(port))
                 .build();
+
         service.addTenant(newTenant);
     }
 }
diff --git a/apps/xos-integration/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/xos-integration/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 9c95117..92fca62 100644
--- a/apps/xos-integration/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/xos-integration/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -29,9 +29,13 @@
             <action class="org.onosproject.xosintegration.cli.VoltRemoveTenantCommand"/>
             <completers>
                 <ref component-id="tenantIdCompleter"/>
+                <ref component-id="placeholderCompleter"/>
+                <ref component-id="connectPointCompleter"/>
                 <null/>
             </completers>
         </command>
     </command-bundle>
     <bean id="tenantIdCompleter" class="org.onosproject.xosintegration.cli.TenantIdCompleter"/>
+    <bean id="placeholderCompleter" class="org.onosproject.cli.PlaceholderCompleter"/>
+    <bean id="connectPointCompleter" class="org.onosproject.cli.net.ConnectPointCompleter"/>
 </blueprint>