[ONOS-6316]create gRPC northbound Host Service and add unit tests

Change-Id: I385f52576000affd2523579c6a6f4c6d57e69938
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ConnectPointProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ConnectPointProtoTranslator.java
index c0177fe..6620096 100644
--- a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ConnectPointProtoTranslator.java
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ConnectPointProtoTranslator.java
@@ -16,7 +16,7 @@
 package org.onosproject.incubator.protobuf.models.net;
 
 import org.onlab.packet.IpAddress;
-import org.onosproject.grpc.net.models.ConnectPointProtoOuterClass;
+import org.onosproject.grpc.net.models.ConnectPointProtoOuterClass.ConnectPointProto;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.HostId;
@@ -40,7 +40,7 @@
      * @param connectPoint gRPC message
      * @return Optional of equivalent {@link org.onosproject.net.ConnectPoint} or empty if ElementId is not recognized
      */
-    public static Optional<ConnectPoint> translate(ConnectPointProtoOuterClass.ConnectPointProto connectPoint) {
+    public static Optional<ConnectPoint> translate(ConnectPointProto connectPoint) {
         switch (connectPoint.getElementIdCase()) {
             case DEVICE_ID:
                 return Optional.of(new ConnectPoint(DeviceId.deviceId(connectPoint.getDeviceId()),
@@ -65,20 +65,18 @@
      * @param connectPoint {@link org.onosproject.net.ConnectPoint}
      * @return gRPC ConnectPoint message
      */
-    public static ConnectPointProtoOuterClass.ConnectPointProto translate(ConnectPoint connectPoint) {
+    public static ConnectPointProto translate(ConnectPoint connectPoint) {
+
         if (connectPoint.elementId() instanceof DeviceId) {
-            return ConnectPointProtoOuterClass.ConnectPointProto.newBuilder()
-                    .setDeviceId(connectPoint.deviceId().toString())
+            return ConnectPointProto.newBuilder().setDeviceId(connectPoint.deviceId().toString())
                     .setPortNumber(connectPoint.port().toString())
                     .build();
         } else if (connectPoint.elementId() instanceof HostId) {
-            return ConnectPointProtoOuterClass.ConnectPointProto.newBuilder()
-                    .setHostId(connectPoint.hostId().toString())
+            return ConnectPointProto.newBuilder().setHostId(connectPoint.hostId().toString())
                     .setPortNumber(connectPoint.port().toString())
                     .build();
         } else if (connectPoint.ipElementId() instanceof IpElementId) {
-            return ConnectPointProtoOuterClass.ConnectPointProto.newBuilder()
-                    .setIpElementId(connectPoint.ipElementId().toString())
+            return ConnectPointProto.newBuilder().setIpElementId(connectPoint.ipElementId().toString())
                     .setPortNumber(connectPoint.port().toString())
                     .build();
         } else {
@@ -87,8 +85,6 @@
         }
     }
 
-
     // Utility class not intended for instantiation.
     private ConnectPointProtoTranslator() {}
-}
-
+}
\ No newline at end of file
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostIdProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostIdProtoTranslator.java
new file mode 100644
index 0000000..859cca4
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostIdProtoTranslator.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.protobuf.models.net;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.grpc.net.models.HostIdProtoOuterClass.HostIdProto;
+import org.onosproject.net.HostId;
+
+/**
+ * gRPC HostIdProto message to equivalent ONOS HostId conversion related utilities.
+ */
+public final class HostIdProtoTranslator {
+
+    /**
+     * Translates gRPC HostId to {@link HostId}.
+     *
+     * @param hostId gRPC message
+     * @return {@link HostId}
+     */
+    public static HostId translate(HostIdProto hostId) {
+
+        if (hostId.equals(HostIdProto.getDefaultInstance())) {
+            return null;
+        }
+
+        return HostId.hostId(MacAddress.valueOf(hostId.getMac()), VlanId.vlanId((short) hostId.getVlanId()));
+    }
+
+    /**
+     * Translates {@link HostId} to gRPC HostId message.
+     *
+     * @param hostId {@link HostId}
+     * @return gRPC HostId message
+     */
+    public static HostIdProto translate(HostId hostId) {
+
+        if (hostId != null) {
+            return HostIdProto.newBuilder()
+                    .setMac(hostId.mac().toString())
+                    .setVlanId(hostId.vlanId().toShort())
+                    .build();
+        }
+
+        return HostIdProto.getDefaultInstance();
+    }
+
+    // Utility class not intended for instantiation.
+    private HostIdProtoTranslator() {}
+}
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostLocationProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostLocationProtoTranslator.java
new file mode 100644
index 0000000..098a276
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostLocationProtoTranslator.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.protobuf.models.net;
+
+import org.onosproject.grpc.net.models.ConnectPointProtoOuterClass.ConnectPointProto;
+import org.onosproject.grpc.net.models.HostLocationProtoOuterClass.HostLocationProto;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.PortNumber;
+
+/**
+ * gRPC HostLocationProto message to equivalent ONOS Host location conversion related utilities.
+ */
+public final class HostLocationProtoTranslator {
+
+    /**
+     * Translates gRPC HostLocation to {@link HostLocation}.
+     *
+     * @param hostLocation gRPC message
+     * @return {@link HostLocation}
+     */
+    public static HostLocation translate(HostLocationProto hostLocation) {
+
+        if (hostLocation.equals(HostLocationProto.getDefaultInstance())) {
+            return null;
+        }
+
+        return new HostLocation(DeviceId.deviceId(hostLocation.getConnectPoint().getDeviceId()),
+                                PortNumber.portNumber(hostLocation.getConnectPoint().getPortNumber()), 0L);
+    }
+
+    /**
+     * Translates {@link HostLocation} to gRPC HostLocation message.
+     *
+     * @param hostLocation {@link HostLocation}
+     * @return gRPC HostLocation message
+     */
+    public static HostLocationProto translate(HostLocation hostLocation) {
+
+        if (hostLocation != null) {
+            return HostLocationProto.newBuilder()
+                    .setConnectPoint(ConnectPointProto.newBuilder()
+                                             .setDeviceId(hostLocation.deviceId().toString())
+                                             .setPortNumber(hostLocation.port().toString()))
+                    .setTime(hostLocation.time())
+                    .build();
+        }
+
+        return HostLocationProto.getDefaultInstance();
+    }
+
+    // Utility class not intended for instantiation.
+    private HostLocationProtoTranslator() {}
+}
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostProtoTranslator.java
new file mode 100644
index 0000000..c12fd7f
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/HostProtoTranslator.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.protobuf.models.net;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.grpc.net.models.HostProtoOuterClass.HostProto;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultHost;
+import org.onosproject.net.Host;
+
+import java.util.stream.Collectors;
+
+/**
+ * gRPC HostProto message to equivalent ONOS Host conversion related utilities.
+ */
+public final class HostProtoTranslator {
+
+
+    /**
+     * Translates {@link Host} to gRPC Host message.
+     *
+     * @param host {@link Host}
+     * @return gRPC HostProto message
+     */
+    public static HostProto translate(Host host) {
+
+        if (host != null) {
+            return HostProto.newBuilder()
+                    .setHostId(HostIdProtoTranslator.translate(host.id()))
+                    .setConfigured(host.configured())
+                    .setVlan(host.vlan().toShort())
+                    .addAllIpAddresses(host.ipAddresses().stream()
+                                               .map(IpAddress::toString)
+                                               .collect(Collectors.toList()))
+                    .setLocation(HostLocationProtoTranslator.translate(host.location()))
+                    .build();
+        }
+
+        return HostProto.getDefaultInstance();
+    }
+
+    /**
+     * Translates gRPC Host message to {@link Host}.
+     *
+     * @param host gRPC message
+     * @return {@link Host}
+     */
+    public static Host translate(HostProto host) {
+        if (host.equals(HostProto.getDefaultInstance())) {
+            return null;
+        }
+
+        return new DefaultHost(ProviderIdProtoTranslator.translate(host.getProviderId()),
+                               HostIdProtoTranslator.translate(host.getHostId()),
+                               MacAddress.valueOf(host.getHostId().getMac()),
+                               VlanId.vlanId((short) host.getVlan()),
+                               HostLocationProtoTranslator.translate(host.getLocation()),
+                               host.getIpAddressesList().stream().map(x -> IpAddress.valueOf(x))
+                                       .collect(Collectors.toSet()),
+                               DefaultAnnotations.builder().putAll(host.getAnnotationsMap()).build());
+    }
+
+    // Utility class not intended for instantiation.
+    private HostProtoTranslator() {}
+}
diff --git a/incubator/protobuf/models/src/main/proto/net/HostProto.proto b/incubator/protobuf/models/src/main/proto/net/HostProto.proto
index 110e1ab..e5e7b5f 100644
--- a/incubator/protobuf/models/src/main/proto/net/HostProto.proto
+++ b/incubator/protobuf/models/src/main/proto/net/HostProto.proto
@@ -3,6 +3,7 @@
 
 import "net/HostIdProto.proto";
 import "net/HostLocationProto.proto";
+import "net/ProviderIdProto.proto";
 
 package net;
 
@@ -13,5 +14,6 @@
     net.HostLocationProto location = 3;
     repeated string ip_addresses = 4;
     bool configured = 5;
-    map<string, string> annotations = 6;
+    net.ProviderIdProto provider_id = 6;
+    map<string, string> annotations = 7;
 }
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostService.java
new file mode 100644
index 0000000..d5e3660
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostService.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.incubator.protobuf.services.nb;
+
+import com.google.common.annotations.Beta;
+import io.grpc.BindableService;
+import io.grpc.stub.StreamObserver;
+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.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Host;
+import org.onosproject.net.host.HostService;
+import org.onosproject.protobuf.api.GrpcServiceRegistry;
+import org.slf4j.Logger;
+import org.onosproject.grpc.nb.net.host.HostServiceGrpc.HostServiceImplBase;
+import org.onosproject.incubator.protobuf.models.net.ConnectPointProtoTranslator;
+import org.onosproject.incubator.protobuf.models.net.HostProtoTranslator;
+
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostCountRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostCountReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsByVlanRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsByVlanReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsByMacRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsByMacReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsByIpRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getHostsByIpReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getConnectedHostsRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.getConnectedHostsReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.startMonitoringIpRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.startMonitoringIpReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.stopMonitoringIpRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.stopMonitoringIpReply;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.requestMacRequest;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.requestMacReply;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * A server that provides access to the methods exposed by {@link HostService}.
+ */
+@Beta
+@Component(immediate = true)
+public class GrpcNbHostService {
+
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected GrpcServiceRegistry registry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected HostService hostService;
+
+    private static HostServiceNBServerInternal instance = null;
+
+    @Activate
+    public void activate() {
+
+        registry.register(getInnerInstance());
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+
+        registry.unregister(getInnerInstance());
+        log.info("Stoped");
+    }
+
+    /**
+     * Register Host Service, Used for unit testing purposes.
+     *
+     * @return An instance of binding Host service
+     */
+    public InProcessServer<BindableService> registerInProcessServer() {
+        InProcessServer<BindableService> inprocessServer =
+                new InProcessServer(HostServiceNBServerInternal.class);
+        inprocessServer.addServiceToBind(getInnerInstance());
+
+        return inprocessServer;
+    }
+
+    /**
+     * Host Service NorthBound implementation.
+     */
+    private final class HostServiceNBServerInternal extends HostServiceImplBase {
+
+        private HostServiceNBServerInternal() {
+            super();
+        }
+
+        @Override
+        public void getHostCount(getHostCountRequest request,
+                                 StreamObserver<getHostCountReply> responseObserver) {
+
+            responseObserver.onNext(getHostCountReply.newBuilder()
+                                            .setHostCount(hostService.getHostCount())
+                                            .build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getHosts(getHostsRequest request,
+                             StreamObserver<getHostsReply> responseObserver) {
+
+            getHostsReply.Builder replyBuilder = getHostsReply.newBuilder();
+
+            hostService.getHosts().forEach(d -> replyBuilder.addHost(HostProtoTranslator.translate(d)));
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getHost(getHostRequest request,
+                            StreamObserver<getHostReply> responseObserver) {
+
+            Host host = hostService.getHost(HostId.hostId(request.getHostId().toString()));
+
+            responseObserver.onNext(getHostReply.newBuilder().setHost(HostProtoTranslator.translate(host)).build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getHostsByVlan(getHostsByVlanRequest request,
+                                   StreamObserver<getHostsByVlanReply> responseObserver) {
+
+            getHostsByVlanReply.Builder replyBuilder = getHostsByVlanReply.newBuilder();
+
+            hostService.getHostsByVlan(VlanId.vlanId(request.getVlanId())).forEach(
+                    d -> replyBuilder.addHost(HostProtoTranslator.translate(d)));
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getHostsByMac(getHostsByMacRequest request,
+                                  StreamObserver<getHostsByMacReply> responseObserver) {
+
+            getHostsByMacReply.Builder replyBuilder = getHostsByMacReply.newBuilder();
+
+            hostService.getHostsByMac(MacAddress.valueOf(request.getMac())).forEach(
+                    d -> replyBuilder.addHost(HostProtoTranslator.translate(d)));
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getHostsByIp(getHostsByIpRequest request,
+                                 StreamObserver<getHostsByIpReply> responseObserver) {
+
+            getHostsByIpReply.Builder replyBuilder = getHostsByIpReply.newBuilder();
+
+            hostService.getHostsByIp(IpAddress.valueOf(request.getIpAddress())).forEach(
+                    d -> replyBuilder.addHost(HostProtoTranslator.translate(d)));
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getConnectedHosts(getConnectedHostsRequest request,
+                                      StreamObserver<getConnectedHostsReply> responseObserver) {
+
+            getConnectedHostsReply.Builder replyBuilder = getConnectedHostsReply.newBuilder();
+
+            if (getConnectedHostsRequest.ConnectedHostCase.DEVICEID == request.getConnectedHostCase()) {
+                hostService.getConnectedHosts(DeviceId.deviceId(request.getDeviceId()))
+                        .forEach(d -> replyBuilder.addHost(HostProtoTranslator.translate(d)));
+            } else if (getConnectedHostsRequest.ConnectedHostCase.CONNECT_POINT == request.getConnectedHostCase()) {
+                hostService.getConnectedHosts(ConnectPointProtoTranslator.translate(request.getConnectPoint()).get())
+                        .forEach(d -> replyBuilder.addHost(HostProtoTranslator.translate(d)));
+            } else {
+                log.warn("Both DeviceId and ConnectPoint are not set.");
+            }
+
+            responseObserver.onNext(replyBuilder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void startMonitoringIp(startMonitoringIpRequest request,
+                                      StreamObserver<startMonitoringIpReply> responseObserver) {
+
+            hostService.startMonitoringIp(IpAddress.valueOf(request.getIpAddress()));
+            responseObserver.onNext(startMonitoringIpReply.getDefaultInstance());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void stopMonitoringIp(stopMonitoringIpRequest request,
+                                     StreamObserver<stopMonitoringIpReply> responseObserver) {
+
+            hostService.stopMonitoringIp(IpAddress.valueOf(request.getIpAddress()));
+            responseObserver.onNext(stopMonitoringIpReply.getDefaultInstance());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void requestMac(requestMacRequest request,
+                               StreamObserver<requestMacReply> responseObserver) {
+
+            hostService.requestMac(IpAddress.valueOf(request.getIpAddress()));
+            responseObserver.onNext(requestMacReply.getDefaultInstance());
+            responseObserver.onCompleted();
+        }
+    }
+
+    private HostServiceNBServerInternal getInnerInstance() {
+        if (instance == null) {
+            instance = new HostServiceNBServerInternal();
+        }
+        return instance;
+    }
+}
diff --git a/incubator/protobuf/services/nb/src/main/proto/net/host/HostServiceNb.proto b/incubator/protobuf/services/nb/src/main/proto/net/host/HostServiceNb.proto
new file mode 100644
index 0000000..81debba
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/proto/net/host/HostServiceNb.proto
@@ -0,0 +1,119 @@
+syntax="proto3";
+option java_package = "org.onosproject.grpc.nb.net.host";
+
+package nb.net.host;
+
+import "net/HostProto.proto";
+import "net/HostIdProto.proto";
+import "net/ConnectPointProto.proto";
+
+message getHostCountRequest {
+}
+
+message getHostCountReply {
+    int32 host_count = 1;
+}
+
+message getHostsRequest {
+}
+
+message getHostsReply {
+    repeated .net.HostProto host = 1;
+}
+
+message getHostRequest {
+    .net.HostIdProto host_id = 1;
+}
+
+message getHostReply {
+    .net.HostProto host = 1;
+}
+
+message getHostsByVlanRequest {
+    string vlan_id = 1;
+}
+
+message getHostsByVlanReply {
+    repeated .net.HostProto host = 1;
+}
+
+message getHostsByMacRequest {
+    string mac = 1;
+}
+
+message getHostsByMacReply {
+    repeated .net.HostProto host = 1;
+}
+
+message getHostsByIpRequest {
+    string ip_address = 1;
+}
+
+message getHostsByIpReply {
+    repeated .net.HostProto host = 1;
+}
+
+message getConnectedHostsRequest {
+    oneof connected_host {
+        .net.ConnectPointProto connect_point = 1;
+        string deviceId = 2;
+    }
+}
+
+message getConnectedHostsReply {
+    repeated .net.HostProto host = 1;
+}
+
+message startMonitoringIpRequest {
+    string ip_address = 1;
+}
+
+message startMonitoringIpReply {
+}
+
+message stopMonitoringIpRequest {
+    string ip_address = 1;
+}
+
+message stopMonitoringIpReply {
+}
+
+message requestMacRequest {
+    string ip_address = 1;
+}
+
+message requestMacReply {
+}
+
+// Host Interface exported by the server.
+service HostService {
+    // GRPC Obtains the host count.
+    rpc getHostCount(getHostCountRequest) returns (getHostCountReply) {}
+
+    // GRPC Obtains the hosts.
+    rpc getHosts(getHostsRequest) returns (getHostsReply) {}
+
+    // GRPC Obtains the host at a given HostId.
+    rpc getHost(getHostRequest) returns (getHostReply) {}
+
+    // GRPC Obtains the hosts at a given VlanId.
+    rpc getHostsByVlan(getHostsByVlanRequest) returns (getHostsByVlanReply) {}
+
+    // GRPC Obtains the hosts at a given MacAddress.
+    rpc getHostsByMac(getHostsByMacRequest) returns (getHostsByMacReply) {}
+
+    // GRPC Obtains the hosts at a given IpAddress.
+    rpc getHostsByIp(getHostsByIpRequest) returns (getHostsByIpReply) {}
+
+    // GRPC Obtains the hosts at a given connectPoint or DeviceId.
+    rpc getConnectedHosts(getConnectedHostsRequest) returns (getConnectedHostsReply) {}
+
+    // GRPC Requests the host service to monitor hosts with the given IP address.
+    rpc startMonitoringIp(startMonitoringIpRequest) returns (startMonitoringIpReply) {}
+
+    // GRPC Stops the host service from monitoring an IP address.
+    rpc stopMonitoringIp(stopMonitoringIpRequest) returns (stopMonitoringIpReply) {}
+
+    // GRPC Requests the host service to resolve the MAC address for the given IP address.
+    rpc requestMac(requestMacRequest) returns (requestMacReply) {}
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostServiceTest.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostServiceTest.java
new file mode 100644
index 0000000..62e5cfa
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostServiceTest.java
@@ -0,0 +1,435 @@
+/*
+* Copyright 2017-present Open Networking Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.onosproject.incubator.protobuf.services.nb;
+
+import com.google.common.collect.ImmutableSet;
+import io.grpc.BindableService;
+import io.grpc.inprocess.InProcessChannelBuilder;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import io.grpc.ManagedChannel;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.grpc.net.models.HostProtoOuterClass;
+import org.onosproject.incubator.protobuf.models.net.HostProtoTranslator;
+import org.onosproject.incubator.protobuf.models.net.HostIdProtoTranslator;
+import org.onosproject.incubator.protobuf.models.net.ConnectPointProtoTranslator;
+import org.onosproject.grpc.nb.net.host.HostServiceGrpc.HostServiceBlockingStub;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultHost;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+
+import org.onosproject.grpc.nb.net.host.HostServiceGrpc;
+import org.onosproject.net.provider.ProviderId;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.grpc.nb.net.host.HostServiceNb.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Unit tests of gRPC northbound host service.
+ */
+public class GrpcNbHostServiceTest {
+    private final Logger log = getLogger(getClass());
+
+    private static InProcessServer<BindableService> inprocessServer;
+    private static HostServiceBlockingStub blockingStub;
+    private static ManagedChannel channel;
+    private static final HostService MOCK_HOST = new MockHostService();
+    private static List<Host> allHosts = new ArrayList<>();
+    private static Host h1;
+    private static HostId id1;
+    private static IpAddress ip1;
+    private static MacAddress mac1;
+    private static DeviceId deviceId;
+    private static ConnectPoint c1;
+    private static boolean started = false;
+    private static boolean stopped = false;
+    private static boolean requestMac = false;
+
+    public GrpcNbHostServiceTest() {}
+
+    private static void populateHosts() {
+        ip1 = IpAddress.valueOf("10.1.1.1");
+        IpAddress ip2 = IpAddress.valueOf("10.1.1.2");
+        IpAddress ip3 = IpAddress.valueOf("10.1.1.3");
+        mac1 = MacAddress.valueOf("67:11:23:45:87:11");
+        MacAddress mac2 = MacAddress.valueOf("67:11:23:45:87:12");
+        MacAddress mac3 = MacAddress.valueOf("67:11:23:45:87:13");
+        id1 = HostId.hostId(mac1);
+        HostId id2 = HostId.hostId(mac2);
+        HostId id3 = HostId.hostId(mac3);
+        deviceId = DeviceId.deviceId("test");
+
+        c1 = new ConnectPoint(deviceId, PortNumber.portNumber(101));
+        HostLocation hostLocation1 = new HostLocation(deviceId, PortNumber.portNumber(101), 0);
+        HostLocation hostLocation2 = new HostLocation(deviceId, PortNumber.portNumber(102), 0);
+        HostLocation hostLocation3 = new HostLocation(deviceId, PortNumber.portNumber(103), 0);
+
+        h1 = new DefaultHost(ProviderId.NONE, id1, mac1, VlanId.NONE,
+                             hostLocation1, ImmutableSet.of(ip1));
+        allHosts.add(h1);
+        allHosts.add(new DefaultHost(ProviderId.NONE, id2, mac2, VlanId.NONE,
+                                     hostLocation2, ImmutableSet.of(ip2)));
+        allHosts.add(new DefaultHost(ProviderId.NONE, id3, mac3, VlanId.NONE,
+                                     hostLocation3, ImmutableSet.of(ip3)));
+    }
+
+    /**
+     * Tests gRPC getComponentNames interface.
+     */
+    @Test
+    public void testGetHostCount() throws InterruptedException {
+        getHostCountRequest request = getHostCountRequest.getDefaultInstance();
+        getHostCountReply reply;
+
+        try {
+            reply = blockingStub.getHostCount(request);
+            assertTrue(allHosts.size() == reply.getHostCount());
+        } catch (Exception e) {
+            log.error("Get host count error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC getComponentNames interface.
+     */
+    @Test
+    public void testGetHosts() throws InterruptedException {
+        getHostsRequest request = getHostsRequest.getDefaultInstance();
+        getHostsReply reply;
+
+        try {
+            reply = blockingStub.getHosts(request);
+            Set<Host> actualHosts = new HashSet<>();
+            for (HostProtoOuterClass.HostProto host : reply.getHostList()) {
+                actualHosts.add(HostProtoTranslator.translate(host));
+            }
+
+            Set<Host> expectedHosts = new HashSet<>();
+            for (Host h : allHosts) {
+                expectedHosts.add(h);
+            }
+            assertTrue(actualHosts.equals(expectedHosts));
+        } catch (Exception e) {
+            log.error("Get all hosts error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC getHost interface.
+     */
+    @Test
+    public void testGetHost() throws InterruptedException {
+        getHostRequest request = getHostRequest.newBuilder().setHostId(HostIdProtoTranslator.translate(id1)).build();
+        getHostReply reply;
+
+        try {
+            reply = blockingStub.getHost(request);
+            assertTrue(HostProtoTranslator.translate(reply.getHost()).equals(h1));
+        } catch (Exception e) {
+            log.error("Get host with hostId error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC getHostsByVlan interface.
+     */
+    @Test
+    public void testGetHostsByVlan() throws InterruptedException {
+        getHostsByVlanRequest request = getHostsByVlanRequest.newBuilder().setVlanId(VlanId.NONE.toString()).build();
+        getHostsByVlanReply reply;
+
+        try {
+            reply = blockingStub.getHostsByVlan(request);
+
+            Set<Host> actualHosts = new HashSet<>();
+            for (HostProtoOuterClass.HostProto host : reply.getHostList()) {
+                actualHosts.add(HostProtoTranslator.translate(host));
+            }
+
+            Set<Host> expectedHosts = new HashSet<>();
+            for (Host h : allHosts) {
+                expectedHosts.add(h);
+            }
+            assertTrue(actualHosts.equals(expectedHosts));
+        } catch (Exception e) {
+            log.error("Get hosts that belong to the specified VLAN error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC getHostsByMac interface.
+     */
+    @Test
+    public void testGetHostsByMac() throws InterruptedException {
+        getHostsByMacRequest request = getHostsByMacRequest.newBuilder().setMac(mac1.toString()).build();
+        getHostsByMacReply reply;
+
+        try {
+            reply = blockingStub.getHostsByMac(request);
+
+            Set<Host> actualHosts = new HashSet<>();
+            for (HostProtoOuterClass.HostProto host : reply.getHostList()) {
+                actualHosts.add(HostProtoTranslator.translate(host));
+            }
+            Set<Host> expectedHosts = new HashSet<>();
+            expectedHosts.add(allHosts.get(0));
+            assertTrue(actualHosts.equals(expectedHosts));
+        } catch (Exception e) {
+            log.error("Get hosts that have the specified MAC address error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC getHostsByIp interface.
+     */
+    @Test
+    public void testGetHostsByIp() throws InterruptedException {
+        getHostsByIpRequest request = getHostsByIpRequest.newBuilder().setIpAddress(ip1.toString()).build();
+        getHostsByIpReply reply;
+
+        try {
+            reply = blockingStub.getHostsByIp(request);
+
+            Set<Host> actualHosts = new HashSet<>();
+            for (HostProtoOuterClass.HostProto host : reply.getHostList()) {
+                actualHosts.add(HostProtoTranslator.translate(host));
+            }
+
+            Set<Host> expectedHosts = new HashSet<>();
+            expectedHosts.add(allHosts.get(0));
+            assertTrue(actualHosts.equals(expectedHosts));
+        } catch (Exception e) {
+            log.error("Get hosts that have the specified IP address error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC getConnectedHosts interface.
+     */
+    @Test
+    public void testGetConnectedHosts() throws InterruptedException {
+        getConnectedHostsRequest request = getConnectedHostsRequest.newBuilder()
+                .setConnectPoint(ConnectPointProtoTranslator.translate(c1))
+                .build();
+        getConnectedHostsReply reply;
+
+        try {
+            reply = blockingStub.getConnectedHosts(request);
+
+            Set<Host> actualHosts = new HashSet<>();
+            for (HostProtoOuterClass.HostProto host : reply.getHostList()) {
+                actualHosts.add(HostProtoTranslator.translate(host));
+            }
+
+            Set<Host> expectedHosts = new HashSet<>();
+            expectedHosts.add(allHosts.get(0));
+            assertTrue(actualHosts.equals(expectedHosts));
+        } catch (Exception e) {
+            log.error("Get connected hosts with connect point error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC getConnectedHostsByDeviceId interface.
+     */
+    @Test
+    public void testGetConnectedHostsByDeviceId() throws InterruptedException {
+        getConnectedHostsRequest request = getConnectedHostsRequest.newBuilder()
+                .setDeviceId(deviceId.toString())
+                .build();
+        getConnectedHostsReply reply;
+
+        try {
+            reply = blockingStub.getConnectedHosts(request);
+
+            Set<Host> actualHosts = new HashSet<>();
+            for (HostProtoOuterClass.HostProto host : reply.getHostList()) {
+                actualHosts.add(HostProtoTranslator.translate(host));
+            }
+
+            Set<Host> expectedHosts = new HashSet<>();
+            for (Host h : allHosts) {
+                expectedHosts.add(h);
+            }
+            assertTrue(actualHosts.equals(expectedHosts));
+        } catch (Exception e) {
+            log.error("Get connected hosts with deviceId error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC startMonitoringIp interface.
+     */
+    @Test
+    public void testStartMonitoringIp() throws InterruptedException {
+        startMonitoringIpRequest request = startMonitoringIpRequest.newBuilder().setIpAddress(ip1.toString()).build();
+
+        try {
+            blockingStub.startMonitoringIp(request);
+            assertTrue(started);
+        } catch (Exception e) {
+            log.error("Start monitoring hosts with the given IP address error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC stopMonitoringIp interface.
+     */
+    @Test
+    public void testStopMonitoringIp() throws InterruptedException {
+        stopMonitoringIpRequest request = stopMonitoringIpRequest.newBuilder().setIpAddress(ip1.toString()).build();
+
+        try {
+            blockingStub.stopMonitoringIp(request);
+            assertTrue(stopped);
+        } catch (Exception e) {
+            log.error("Stop monitoring hosts with the given IP address error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Tests gRPC requestMac interface.
+     */
+    @Test
+    public void testRequestMac() throws InterruptedException {
+        requestMacRequest request = requestMacRequest.newBuilder().setIpAddress(ip1.toString()).build();
+
+        try {
+            blockingStub.requestMac(request);
+            assertTrue(requestMac);
+        } catch (Exception e) {
+            log.error("Resolve the MAC address for the given IP address error! Exception={}", e.toString());
+        }
+    }
+
+    /**
+     * Initialization before start testing gRPC northbound host service.
+     */
+    @BeforeClass
+    public static void beforeClass() throws InstantiationException, IllegalAccessException, IOException {
+        GrpcNbHostService hostService = new GrpcNbHostService();
+        hostService.hostService = MOCK_HOST;
+        inprocessServer = hostService.registerInProcessServer();
+
+        inprocessServer.start();
+        channel = InProcessChannelBuilder.forName("test").directExecutor()
+                // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
+                // needing certificates.
+                .usePlaintext(true).build();
+        blockingStub = HostServiceGrpc.newBlockingStub(channel);
+        populateHosts();
+    }
+
+    /**
+     * Finalization after test gRPC northbound host service.
+     */
+    @AfterClass
+    public static void afterClass() {
+
+        channel.shutdownNow();
+        inprocessServer.stop();
+    }
+
+    private static class MockHostService implements HostService {
+
+        MockHostService() {
+        }
+
+        @Override
+        public int getHostCount() {
+            return allHosts.size();
+        }
+
+        @Override
+        public Iterable<Host> getHosts() {
+            return allHosts;
+        }
+
+        @Override
+        public Host getHost(HostId hostId) {
+            return allHosts.stream().filter(h -> h.id().equals(hostId)).findFirst().get();
+        }
+
+        @Override
+        public Set<Host> getHostsByVlan(VlanId vlanId) {
+            return allHosts.stream().filter(h -> h.vlan().equals(vlanId)).collect(Collectors.toSet());
+        }
+
+        @Override
+        public Set<Host> getHostsByMac(MacAddress mac) {
+            return allHosts.stream().filter(h -> h.mac().equals(mac)).collect(Collectors.toSet());
+        }
+
+        @Override
+        public Set<Host> getHostsByIp(IpAddress ip) {
+            return allHosts.stream().filter(h -> h.ipAddresses().contains(ip)).collect(Collectors.toSet());
+        }
+
+        @Override
+        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
+            return allHosts.stream().filter(h -> h.location().deviceId().equals(connectPoint.deviceId())
+                    && h.location().port().equals(connectPoint.port()))
+                    .collect(Collectors.toSet());
+        }
+
+        @Override
+        public Set<Host> getConnectedHosts(DeviceId deviceId) {
+            return allHosts.stream().filter(h -> h.location().deviceId().equals(deviceId)).collect(Collectors.toSet());
+        }
+
+        @Override
+        public void startMonitoringIp(IpAddress ip) {
+            started = true;
+        }
+
+        @Override
+        public void stopMonitoringIp(IpAddress ip) {
+            stopped = true;
+        }
+
+        @Override
+        public void requestMac(IpAddress ip) {
+            requestMac = true;
+        }
+
+        @Override
+        public void addListener(HostListener listener) {
+        }
+
+        @Override
+        public void removeListener(HostListener listener) {
+        }
+    }
+}