Added bi-directional nature to HostToHost intent.
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/AddHostToHostIntentCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/AddHostToHostIntentCommand.java
new file mode 100644
index 0000000..be2e964
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/net/AddHostToHostIntentCommand.java
@@ -0,0 +1,48 @@
+package org.onlab.onos.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.onos.cli.AbstractShellCommand;
+import org.onlab.onos.net.HostId;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.DefaultTrafficTreatment;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.intent.HostToHostIntent;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.intent.IntentService;
+
+/**
+ * Installs host-to-host connectivity intent.
+ */
+@Command(scope = "onos", name = "add-host-intent",
+         description = "Installs host-to-host connectivity intent")
+public class AddHostToHostIntentCommand extends AbstractShellCommand {
+
+    @Argument(index = 0, name = "one", description = "One host ID",
+              required = true, multiValued = false)
+    String one = null;
+
+    @Argument(index = 1, name = "two", description = "Another host ID",
+              required = true, multiValued = false)
+    String two = null;
+
+    private static long id = 1;
+
+    @Override
+    protected void execute() {
+        IntentService service = get(IntentService.class);
+
+        HostId oneId = HostId.hostId(one);
+        HostId twoId = HostId.hostId(two);
+
+        TrafficSelector selector = DefaultTrafficSelector.builder().build();
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+
+        HostToHostIntent intent =
+                new HostToHostIntent(new IntentId(id++), oneId, twoId,
+                                     selector, treatment);
+        service.submit(intent);
+    }
+
+}
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/IntentInstallCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/IntentInstallCommand.java
deleted file mode 100644
index 90b7311..0000000
--- a/cli/src/main/java/org/onlab/onos/cli/net/IntentInstallCommand.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package org.onlab.onos.cli.net;
-
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onlab.onos.cli.AbstractShellCommand;
-import org.onlab.onos.net.HostId;
-import org.onlab.onos.net.flow.DefaultTrafficSelector;
-import org.onlab.onos.net.flow.DefaultTrafficTreatment;
-import org.onlab.onos.net.flow.TrafficSelector;
-import org.onlab.onos.net.flow.TrafficTreatment;
-import org.onlab.onos.net.host.HostService;
-import org.onlab.onos.net.intent.HostToHostIntent;
-import org.onlab.onos.net.intent.IntentId;
-import org.onlab.onos.net.intent.IntentService;
-
-/**
- * Lists all shortest-paths paths between the specified source and
- * destination devices.
- */
-@Command(scope = "onos", name = "add-intent",
-         description = "Installs HostToHostIntent between the specified source and destination devices")
-public class IntentInstallCommand extends AbstractShellCommand {
-
-    @Argument(index = 0, name = "src", description = "Source device ID",
-              required = true, multiValued = false)
-    String src = null;
-
-    @Argument(index = 1, name = "dst", description = "Destination device ID",
-              required = true, multiValued = false)
-    String dst = null;
-
-    private static long id = 1;
-
-    @Override
-    protected void execute() {
-        IntentService service = get(IntentService.class);
-        HostService hosts = get(HostService.class);
-
-        HostId srcId = HostId.hostId(src);
-        HostId dstId = HostId.hostId(dst);
-
-        TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
-        builder.matchEthSrc(hosts.getHost(srcId).mac())
-                .matchEthDst(hosts.getHost(dstId).mac());
-
-        TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
-
-        HostToHostIntent intent =
-                new HostToHostIntent(new IntentId(id++), srcId, dstId,
-                                     builder.build(), treat.build());
-
-        log.info("Adding intent {}", intent);
-
-        service.submit(intent);
-    }
-
-}
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
new file mode 100644
index 0000000..ad17290
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
@@ -0,0 +1,23 @@
+package org.onlab.onos.cli.net;
+
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.onos.cli.AbstractShellCommand;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentService;
+
+/**
+ * Lists the inventory of intents and their states.
+ */
+@Command(scope = "onos", name = "intents",
+         description = "Lists the inventory of intents and their states")
+public class IntentsListCommand extends AbstractShellCommand {
+
+    @Override
+    protected void execute() {
+        IntentService service = get(IntentService.class);
+        for (Intent intent : service.getIntents()) {
+            print("%s", intent);
+        }
+    }
+
+}
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index a096735..f0516f7 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -56,12 +56,16 @@
                 <ref component-id="deviceIdCompleter"/>
             </completers>
         </command>
+
         <command>
-            <action class="org.onlab.onos.cli.net.IntentInstallCommand"/>
+            <action class="org.onlab.onos.cli.net.AddHostToHostIntentCommand"/>
             <completers>
                 <ref component-id="hostIdCompleter"/>
             </completers>
         </command>
+        <command>
+            <action class="org.onlab.onos.cli.net.IntentsListCommand"/>
+        </command>
 
         <command>
             <action class="org.onlab.onos.cli.net.ClustersListCommand"/>
diff --git a/core/api/src/main/java/org/onlab/onos/net/ConnectPoint.java b/core/api/src/main/java/org/onlab/onos/net/ConnectPoint.java
index 35adde9..17f9348 100644
--- a/core/api/src/main/java/org/onlab/onos/net/ConnectPoint.java
+++ b/core/api/src/main/java/org/onlab/onos/net/ConnectPoint.java
@@ -47,7 +47,23 @@
             return (DeviceId) elementId;
         }
         throw new IllegalStateException("Connection point not associated " +
-                "with an infrastructure device");
+                                                "with an infrastructure device");
+    }
+
+    /**
+     * Returns the identifier of the infrastructure device if the connection
+     * point belongs to a network element which is indeed an end-station host.
+     *
+     * @return network element identifier as a host identifier
+     * @throws java.lang.IllegalStateException if connection point is not
+     *                                         associated with a host
+     */
+    public HostId hostId() {
+        if (elementId instanceof HostId) {
+            return (HostId) elementId;
+        }
+        throw new IllegalStateException("Connection point not associated " +
+                                                "with an end-station host");
     }
 
     /**
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
index 08063f0..7cef3da 100644
--- a/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/HostToHostIntent.java
@@ -10,47 +10,49 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
- * Abstraction of end-station to end-station connectivity.
+ * Abstraction of end-station to end-station bidirectional connectivity.
  */
 public class HostToHostIntent extends ConnectivityIntent {
 
-    private final HostId src;
-    private final HostId dst;
+    private final HostId one;
+    private final HostId two;
 
     /**
      * Creates a new point-to-point intent with the supplied ingress/egress
      * ports.
      *
      * @param intentId  intent identifier
+     * @param one       first host
+     * @param two       second host
      * @param selector  action
      * @param treatment ingress port
      * @throws NullPointerException if {@code ingressPort} or {@code egressPort}
      *                              is null.
      */
-    public HostToHostIntent(IntentId intentId, HostId src, HostId dst,
-                            TrafficSelector selector, TrafficTreatment treatment) {
+    public HostToHostIntent(IntentId intentId, HostId one, HostId two,
+                            TrafficSelector selector,
+                            TrafficTreatment treatment) {
         super(intentId, selector, treatment);
-        this.src = checkNotNull(src);
-        this.dst = checkNotNull(dst);
+        this.one = checkNotNull(one);
+        this.two = checkNotNull(two);
     }
 
     /**
-     * Returns the port on which the ingress traffic should be connected to the
-     * egress.
+     * Returns identifier of the first host.
      *
-     * @return ingress port
+     * @return first host identifier
      */
-    public HostId getSrc() {
-        return src;
+    public HostId one() {
+        return one;
     }
 
     /**
-     * Returns the port on which the traffic should egress.
+     * Returns identifier of the second host.
      *
-     * @return egress port
+     * @return second host identifier
      */
-    public HostId getDst() {
-        return dst;
+    public HostId two() {
+        return two;
     }
 
     @Override
@@ -66,13 +68,13 @@
         }
 
         HostToHostIntent that = (HostToHostIntent) o;
-        return Objects.equals(this.src, that.src)
-                && Objects.equals(this.dst, that.dst);
+        return Objects.equals(this.one, that.one)
+                && Objects.equals(this.two, that.two);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(super.hashCode(), src, dst);
+        return Objects.hash(super.hashCode(), one, two);
     }
 
     @Override
@@ -80,9 +82,9 @@
         return MoreObjects.toStringHelper(getClass())
                 .add("id", getId())
                 .add("selector", getTrafficSelector())
-                .add("treatmetn", getTrafficTreatment())
-                .add("src", src)
-                .add("dst", dst)
+                .add("treatment", getTrafficTreatment())
+                .add("one", one)
+                .add("two", two)
                 .toString();
     }
 
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
index a8bea2e..541a702 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/HostToHostIntentCompiler.java
@@ -1,17 +1,15 @@
 package org.onlab.onos.net.intent.impl;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.Host;
+import org.onlab.onos.net.HostId;
 import org.onlab.onos.net.Path;
-import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.host.HostService;
 import org.onlab.onos.net.intent.HostToHostIntent;
 import org.onlab.onos.net.intent.IdGenerator;
 import org.onlab.onos.net.intent.Intent;
@@ -21,6 +19,12 @@
 import org.onlab.onos.net.intent.PathIntent;
 import org.onlab.onos.net.topology.PathService;
 
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import static org.onlab.onos.net.flow.DefaultTrafficSelector.builder;
+
 /**
  * A intent compiler for {@link HostToHostIntent}.
  */
@@ -34,6 +38,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PathService pathService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected HostService hostService;
+
     private IdGenerator<IntentId> intentIdGenerator;
 
     @Activate
@@ -50,18 +57,34 @@
 
     @Override
     public List<Intent> compile(HostToHostIntent intent) {
-        Set<Path> paths = pathService.getPaths(intent.getSrc(), intent.getDst());
-        if (paths.isEmpty()) {
-            throw new PathNotFoundException();
-        }
-        Path path = paths.iterator().next();
+        Path pathOne = getPath(intent.one(), intent.two());
+        Path pathTwo = getPath(intent.two(), intent.one());
 
-        return Arrays.asList((Intent) new PathIntent(
-                intentIdGenerator.getNewId(),
-                intent.getTrafficSelector(),
-                intent.getTrafficTreatment(),
-                new ConnectPoint(intent.getSrc(), PortNumber.ALL),
-                new ConnectPoint(intent.getDst(), PortNumber.ALL),
-                path));
+        Host one = hostService.getHost(intent.one());
+        Host two = hostService.getHost(intent.two());
+
+        return Arrays.asList(createPathIntent(pathOne, one, two, intent),
+                             createPathIntent(pathTwo, two, one, intent));
+    }
+
+    // Creates a path intent from the specified path and original connectivity intent.
+    private Intent createPathIntent(Path path, Host src, Host dst,
+                                    HostToHostIntent intent) {
+
+        TrafficSelector selector = builder(intent.getTrafficSelector())
+                .matchEthSrc(src.mac()).matchEthDst(dst.mac()).build();
+
+        return new PathIntent(intentIdGenerator.getNewId(),
+                              selector, intent.getTrafficTreatment(),
+                              path.src(), path.dst(), path);
+    }
+
+    private Path getPath(HostId one, HostId two) {
+        Set<Path> paths = pathService.getPaths(one, two);
+        if (paths.isEmpty()) {
+            throw new PathNotFoundException("No path from host " + one + " to " + two);
+        }
+        // TODO: let's be more intelligent about this eventually
+        return paths.iterator().next();
     }
 }
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
index f1c9de3..769e4c7 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
@@ -355,8 +355,8 @@
     private class InternalStoreDelegate implements IntentStoreDelegate {
         @Override
         public void notify(IntentEvent event) {
-            processStoreEvent(event);
             eventDispatcher.post(event);
+            processStoreEvent(event);
         }
     }
 
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
index 84e8c79..ec7841c 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/PathIntentInstaller.java
@@ -1,7 +1,5 @@
 package org.onlab.onos.net.intent.impl;
 
-import java.util.Iterator;
-
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -12,7 +10,6 @@
 import org.onlab.onos.net.Link;
 import org.onlab.onos.net.flow.DefaultFlowRule;
 import org.onlab.onos.net.flow.DefaultTrafficSelector;
-import org.onlab.onos.net.flow.DefaultTrafficTreatment;
 import org.onlab.onos.net.flow.FlowRule;
 import org.onlab.onos.net.flow.FlowRuleService;
 import org.onlab.onos.net.flow.TrafficSelector;
@@ -21,6 +18,10 @@
 import org.onlab.onos.net.intent.IntentInstaller;
 import org.onlab.onos.net.intent.PathIntent;
 
+import java.util.Iterator;
+
+import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
+
 /**
  * Installer for {@link PathIntent path connectivity intents}.
  */
@@ -51,18 +52,16 @@
                 DefaultTrafficSelector.builder(intent.getTrafficSelector());
         Iterator<Link> links = intent.getPath().links().iterator();
         ConnectPoint prev = links.next().dst();
+
         while (links.hasNext()) {
             builder.matchInport(prev.port());
             Link link = links.next();
-
-            TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
-            treat.setOutput(link.src().port());
-
+            TrafficTreatment treatment = builder()
+                    .setOutput(link.src().port()).build();
             FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
-                                                builder.build(), treat.build(),
-                                                10, appId, 30);
+                                                builder.build(), treatment,
+                                                123, appId, 600);
             flowRuleService.applyFlowRules(rule);
-
             prev = link.dst();
         }