Created LinkService and added unit tests.
Change-Id: I1f2104c873e5a9e2df34074d36cddc823e3b3ec5
diff --git a/incubator/protobuf/services/nb/BUCK b/incubator/protobuf/services/nb/BUCK
index 4d9c789..6f582e0 100644
--- a/incubator/protobuf/services/nb/BUCK
+++ b/incubator/protobuf/services/nb/BUCK
@@ -5,11 +5,14 @@
'//incubator/protobuf/models:onos-incubator-protobuf-models-proto',
'//incubator/protobuf/models:onos-incubator-protobuf-models',
'//lib:protobuf-java-3.2.0',
- '//lib:GRPC_1.3'
+ '//lib:GRPC_1.3',
+ '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0',
+ '//lib:grpc-protobuf-lite-1.3.0'
]
GRPC_DEPS = [
'//lib:GRPC_1.3',
+ '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0',
'//incubator/protobuf/models:onos-incubator-protobuf-models-proto',
'//lib:protobuf-java-3.2.0',
'//lib:guava'
@@ -23,6 +26,7 @@
'//lib:protobuf-java-3.2.0',
'//lib:guava',
'//lib:grpc-core-1.3.0',
+ '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0',
'//lib:grpc-protobuf-1.3.0',
'//lib:grpc-stub-1.3.0',
'//lib:grpc-netty-1.3.0',
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbDeviceServiceUtil.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbDeviceServiceUtil.java
deleted file mode 100644
index 0ad1b3f..0000000
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbDeviceServiceUtil.java
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
- * 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.grpc.nb.utils;
-
-import org.onlab.packet.ChassisId;
-import org.onosproject.grpc.net.device.models.DeviceDescriptionProtoOuterClass;
-import org.onosproject.grpc.net.device.models.DeviceDescriptionProtoOuterClass.DeviceDescriptionProto;
-import org.onosproject.grpc.net.device.models.DeviceEnumsProto.DeviceTypeProto;
-import org.onosproject.grpc.net.device.models.DeviceEnumsProto.MastershipRoleProto;
-import org.onosproject.grpc.net.device.models.PortDescriptionProtoOuterClass.PortDescriptionProto;
-import org.onosproject.grpc.net.device.models.PortEnumsProto;
-
-import org.onosproject.grpc.net.device.models.PortStatisticsProtoOuterClass;
-import org.onosproject.grpc.net.device.models.PortStatisticsProtoOuterClass.PortStatisticsProto;
-import org.onosproject.net.Annotations;
-import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.Device.Type;
-import org.onosproject.net.MastershipRole;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.SparseAnnotations;
-import org.onosproject.net.device.DefaultDeviceDescription;
-import org.onosproject.net.device.DefaultPortDescription;
-import org.onosproject.net.device.DefaultPortStatistics;
-import org.onosproject.net.device.DeviceDescription;
-import org.onosproject.net.device.PortDescription;
-import org.onosproject.net.device.PortStatistics;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * gRPC message conversion related utilities for device service.
- */
-public final class GrpcNbDeviceServiceUtil {
-
- private static final Logger log = LoggerFactory.getLogger(GrpcNbDeviceServiceUtil.class);
-
- /**
- * Translates gRPC enum MastershipRole to ONOS enum.
- *
- * @param role mastership role in gRPC enum
- * @return equivalent in ONOS enum
- */
- public static MastershipRole translate(MastershipRoleProto role) {
- switch (role) {
- case NONE:
- return MastershipRole.NONE;
- case MASTER:
- return MastershipRole.MASTER;
- case STANDBY:
- return MastershipRole.STANDBY;
- case UNRECOGNIZED:
- log.warn("Unrecognized MastershipRole gRPC message: {}", role);
- return MastershipRole.NONE;
- default:
- return MastershipRole.NONE;
- }
- }
-
- /**
- * Translates ONOS enum MastershipRole to gRPC enum.
- *
- * @param newRole ONOS' mastership role
- * @return equivalent in gRPC message enum
- */
- public static MastershipRoleProto translate(MastershipRole newRole) {
- switch (newRole) {
- case MASTER:
- return MastershipRoleProto.MASTER;
- case STANDBY:
- return MastershipRoleProto.STANDBY;
- case NONE:
- default:
- return MastershipRoleProto.NONE;
- }
- }
-
-
- /**
- * Translates gRPC DeviceDescription to {@link DeviceDescriptionProtoOuterClass}.
- *
- * @param deviceDescription gRPC message
- * @return {@link DeviceDescriptionProtoOuterClass}
- */
- public static DeviceDescription translate(
- DeviceDescriptionProto deviceDescription) {
- URI uri = URI.create(deviceDescription.getDeviceUri());
- Type type = translate(deviceDescription.getType());
- String manufacturer = deviceDescription.getManufacturer();
- String hwVersion = deviceDescription.getHwVersion();
- String swVersion = deviceDescription.getSwVersion();
- String serialNumber = deviceDescription.getSerialNumber();
- ChassisId chassis = new ChassisId(deviceDescription.getChassisId());
- boolean defaultAvailable = deviceDescription.getIsDefaultAvailable();
- return new DefaultDeviceDescription(uri, type, manufacturer,
- hwVersion, swVersion, serialNumber,
- chassis,
- defaultAvailable,
- asAnnotations(deviceDescription.getAnnotationsMap()));
- }
-
- /**
- * Translates {@link DeviceDescription} to gRPC DeviceDescription message.
- *
- * @param deviceDescription {@link DeviceDescription}
- * @return gRPC DeviceDescription message
- */
- public static DeviceDescriptionProto translate(
- DeviceDescription deviceDescription) {
-
- return DeviceDescriptionProto.newBuilder()
- .setDeviceUri(deviceDescription.deviceUri().toString())
- .setType(translate(deviceDescription.type()))
- .setManufacturer(deviceDescription.manufacturer())
- .setHwVersion(deviceDescription.hwVersion())
- .setSwVersion(deviceDescription.swVersion())
- .setSerialNumber(deviceDescription.serialNumber())
- .setChassisId(deviceDescription.chassisId().toString())
- .setIsDefaultAvailable(deviceDescription.isDefaultAvailable())
- .putAllAnnotations(asMap(deviceDescription.annotations()))
- .build();
- }
-
-
- /**
- * Translates gRPC DeviceType to {@link Type}.
- *
- * @param type gRPC message
- * @return {@link Type}
- */
- public static Type translate(DeviceTypeProto type) {
- switch (type) {
- case BALANCER:
- return Type.BALANCER;
- case CONTROLLER:
- return Type.CONTROLLER;
- case FIBER_SWITCH:
- return Type.FIBER_SWITCH;
- case FIREWALL:
- return Type.FIREWALL;
- case IDS:
- return Type.IDS;
- case IPS:
- return Type.IPS;
- case MICROWAVE:
- return Type.MICROWAVE;
- case OTHER:
- return Type.OTHER;
- case OTN:
- return Type.OTN;
- case ROADM:
- return Type.ROADM;
- case ROADM_OTN:
- return Type.ROADM_OTN;
- case ROUTER:
- return Type.ROUTER;
- case SWITCH:
- return Type.SWITCH;
- case VIRTUAL_DEVICE:
- return Type.VIRTUAL;
-
- case UNRECOGNIZED:
- default:
- log.warn("Unexpected DeviceType: {}", type);
- return Type.OTHER;
- }
- }
-
- /**
- * Translates {@link Type} to gRPC DeviceType.
- *
- * @param type {@link Type}
- * @return gRPC message
- */
- public static DeviceTypeProto translate(Type type) {
- switch (type) {
- case BALANCER:
- return DeviceTypeProto.BALANCER;
- case CONTROLLER:
- return DeviceTypeProto.CONTROLLER;
- case FIBER_SWITCH:
- return DeviceTypeProto.FIBER_SWITCH;
- case FIREWALL:
- return DeviceTypeProto.FIREWALL;
- case IDS:
- return DeviceTypeProto.IDS;
- case IPS:
- return DeviceTypeProto.IPS;
- case MICROWAVE:
- return DeviceTypeProto.MICROWAVE;
- case OTHER:
- return DeviceTypeProto.OTHER;
- case OTN:
- return DeviceTypeProto.OTN;
- case ROADM:
- return DeviceTypeProto.ROADM;
- case ROADM_OTN:
- return DeviceTypeProto.ROADM_OTN;
- case ROUTER:
- return DeviceTypeProto.ROUTER;
- case SWITCH:
- return DeviceTypeProto.SWITCH;
- case VIRTUAL:
- return DeviceTypeProto.VIRTUAL_DEVICE;
-
- default:
- log.warn("Unexpected Device.Type: {}", type);
- return DeviceTypeProto.OTHER;
- }
- }
-
- /**
- * Translates gRPC PortDescription message to {@link PortDescription}.
- *
- * @param portDescription gRPC message
- * @return {@link PortDescription}
- */
- public static PortDescription translate(PortDescriptionProto portDescription) {
- PortNumber number = PortNumber.fromString(portDescription.getPortNumber());
- boolean isEnabled = portDescription.getIsEnabled();
- Port.Type type = translate(portDescription.getType());
- long portSpeed = portDescription.getPortSpeed();
- SparseAnnotations annotations = asAnnotations(portDescription.getAnnotationsMap());
- // TODO How to deal with more specific Port...
- return new DefaultPortDescription(number, isEnabled, type, portSpeed, annotations);
- }
-
- /**
- * Translates {@link PortDescription} to gRPC PortDescription message.
- *
- * @param portDescription {@link PortDescription}
- * @return gRPC PortDescription message
- */
- public static PortDescriptionProto translate(PortDescription portDescription) {
- return PortDescriptionProto.newBuilder()
- .setPortNumber(portDescription.portNumber().toString())
- .setIsEnabled(portDescription.isEnabled())
- .setType(translate(portDescription.type()))
- .setPortSpeed(portDescription.portSpeed())
- .putAllAnnotations(asMap(portDescription.annotations()))
- .build();
- }
-
- /**
- * Translates gRPC PortType to {@link Port.Type}.
- *
- * @param type gRPC message
- * @return {@link Port.Type}
- */
- public static Port.Type translate(PortEnumsProto.PortTypeProto type) {
- switch (type) {
- case COPPER:
- return Port.Type.COPPER;
- case FIBER:
- return Port.Type.FIBER;
- case OCH:
- return Port.Type.OCH;
- case ODUCLT:
- return Port.Type.ODUCLT;
- case OMS:
- return Port.Type.OMS;
- case PACKET:
- return Port.Type.PACKET;
- case VIRTUAL_PORT:
- return Port.Type.VIRTUAL;
-
- case UNRECOGNIZED:
- default:
- log.warn("Unexpected PortType: {}", type);
- return Port.Type.COPPER;
- }
- }
-
- /**
- * Translates {@link Port.Type} to gRPC PortType.
- *
- * @param type {@link Port.Type}
- * @return gRPC message
- */
- public static PortEnumsProto.PortTypeProto translate(Port.Type type) {
- switch (type) {
- case COPPER:
- return PortEnumsProto.PortTypeProto.COPPER;
- case FIBER:
- return PortEnumsProto.PortTypeProto.FIBER;
- case OCH:
- return PortEnumsProto.PortTypeProto.OCH;
- case ODUCLT:
- return PortEnumsProto.PortTypeProto.ODUCLT;
- case OMS:
- return PortEnumsProto.PortTypeProto.OMS;
- case PACKET:
- return PortEnumsProto.PortTypeProto.PACKET;
- case VIRTUAL:
- return PortEnumsProto.PortTypeProto.VIRTUAL_PORT;
-
- default:
- log.warn("Unexpected Port.Type: {}", type);
- return PortEnumsProto.PortTypeProto.COPPER;
- }
- }
-
- /**
- * Translates gRPC PortStatistics message to {@link PortStatisticsProtoOuterClass}.
- *
- * @param portStatistics gRPC PortStatistics message
- * @return {@link PortStatisticsProtoOuterClass}
- */
- public static PortStatistics translate(PortStatisticsProto portStatistics) {
- // TODO implement adding missing fields
- return DefaultPortStatistics.builder()
- .setPort(portStatistics.getPort())
- .setPacketsReceived(portStatistics.getPacketsReceived())
- .setPacketsSent(portStatistics.getPacketsSent())
- .build();
- }
-
- /**
- * Translates {@link PortStatistics} to gRPC PortStatistics message.
- *
- * @param portStatistics {@link PortStatistics}
- * @return gRPC PortStatistics message
- */
- public static PortStatisticsProto translate(PortStatistics portStatistics) {
- // TODO implement adding missing fields
- return PortStatisticsProto.newBuilder()
- .setPort(portStatistics.port())
- .setPacketsReceived(portStatistics.packetsReceived())
- .setPacketsSent(portStatistics.packetsSent())
- .build();
- }
-
- // may be this can be moved to Annotation itself or AnnotationsUtils
- /**
- * Converts Annotations to Map of Strings.
- *
- * @param annotations {@link Annotations}
- * @return Map of annotation key and values
- */
- public static Map<String, String> asMap(Annotations annotations) {
- if (annotations instanceof DefaultAnnotations) {
- return ((DefaultAnnotations) annotations).asMap();
- }
- Map<String, String> map = new HashMap<>();
- annotations.keys()
- .forEach(k -> map.put(k, annotations.value(k)));
-
- return map;
- }
-
- // may be this can be moved to Annotation itself or AnnotationsUtils
- /**
- * Converts Map of Strings to {@link SparseAnnotations}.
- *
- * @param annotations Map of annotation key and values
- * @return {@link SparseAnnotations}
- */
- public static SparseAnnotations asAnnotations(Map<String, String> annotations) {
- DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
- annotations.entrySet().forEach(e -> {
- if (e.getValue() != null) {
- builder.set(e.getKey(), e.getValue());
- } else {
- builder.remove(e.getKey());
- }
- });
- return builder.build();
- }
-
- // Utility class not intended for instantiation.
- private GrpcNbDeviceServiceUtil() {}
-}
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java
deleted file mode 100644
index 341744c..0000000
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * A package contains a set of utilities that are used to convert gRPC model
- * object to ONOS data model object.
- */
-package org.onosproject.grpc.nb.utils;
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
similarity index 99%
rename from incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java
rename to incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
index 1e1bdc9..df85f18 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
@@ -33,7 +33,7 @@
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
-import org.onosproject.grpc.nb.utils.GrpcNbDeviceServiceUtil;
+import org.onosproject.incubator.protobuf.models.GrpcNbDeviceServiceUtil;
import static org.onosproject.grpc.nb.net.device.DeviceServiceNb.*;
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkService.java
new file mode 100644
index 0000000..d6d7d61
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkService.java
@@ -0,0 +1,216 @@
+/*
+* 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 org.onosproject.incubator.protobuf.models.net.ConnectPointProtoTranslator;
+import org.onosproject.incubator.protobuf.models.net.LinkProtoTranslator;
+
+import com.google.common.annotations.Beta;
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+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.onosproject.grpc.nb.net.link.LinkServiceGrpc.LinkServiceImplBase;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.link.LinkService;
+
+import java.io.IOException;
+
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkCountRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkCountReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getActiveLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getActiveLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceEgressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceEgressLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceIngressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceIngressLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getEgressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getEgressLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getIngressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getIngressLinksReply;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A server that provides access to the methods exposed by {@link org.onosproject.net.link.LinkService}.
+ */
+@Beta
+@Component(immediate = true)
+public class GrpcNbLinkService {
+
+ private static final Logger log = LoggerFactory.getLogger(GrpcNbLinkService.class);
+
+
+ private Server server;
+ private LinkServiceNBServerInternal innerClassInstance = null;
+
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkService linkService;
+
+ @Activate
+ public void activate() {
+ server = ServerBuilder.forPort(64000).addService(getInnerClassInstance()).build();
+ try {
+ server.start();
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+
+ @Deactivate
+ public void deactivate() {
+ server.shutdown();
+ }
+
+ public class LinkServiceNBServerInternal extends LinkServiceImplBase {
+
+ public LinkServiceNBServerInternal() {
+ super();
+ }
+
+ @Override
+ public void getLinkCount(getLinkCountRequest request,
+ StreamObserver<getLinkCountReply> responseObserver) {
+ responseObserver
+ .onNext(getLinkCountReply
+ .newBuilder()
+ .setLinkCount(linkService.getLinkCount())
+ .build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getLink(getLinkRequest request,
+ StreamObserver<getLinkReply> responseObserver) {
+ ConnectPoint src = ConnectPointProtoTranslator.translate(request.getSrc()).get();
+ ConnectPoint dst = ConnectPointProtoTranslator.translate(request.getDst()).get();
+
+ org.onosproject.net.Link link = linkService.getLink(src, dst);
+ getLinkReply reply = getLinkReply.newBuilder()
+ .setLink(LinkProtoTranslator.translate(link)).build();
+
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getActiveLinks(getActiveLinksRequest request,
+ StreamObserver<getActiveLinksReply> responseObserver) {
+ getActiveLinksReply.Builder builder = getActiveLinksReply.newBuilder();
+ linkService.getActiveLinks().forEach(l -> {
+ builder.addLink(LinkProtoTranslator.translate(l));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getDeviceLinks(getDeviceLinksRequest request,
+ StreamObserver<getDeviceLinksReply> responseObserver) {
+ DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+ getDeviceLinksReply.Builder builder = getDeviceLinksReply.newBuilder();
+ linkService.getDeviceLinks(deviceId).forEach(l -> {
+ builder.addLink(LinkProtoTranslator.translate(l));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getDeviceEgressLinks(getDeviceEgressLinksRequest request,
+ StreamObserver<getDeviceEgressLinksReply> responseObserver) {
+ DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+ getDeviceEgressLinksReply.Builder builder = getDeviceEgressLinksReply.newBuilder();
+ linkService.getDeviceEgressLinks(deviceId).forEach(l -> {
+ builder.addLink(LinkProtoTranslator.translate(l));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getDeviceIngressLinks(getDeviceIngressLinksRequest request,
+ StreamObserver<getDeviceIngressLinksReply> responseObserver) {
+ DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+ getDeviceIngressLinksReply.Builder builder = getDeviceIngressLinksReply.newBuilder();
+ linkService.getDeviceIngressLinks(deviceId).forEach(l -> {
+ builder.addLink(LinkProtoTranslator.translate(l));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getEgressLinks(getEgressLinksRequest request,
+ StreamObserver<getEgressLinksReply> responseObserver) {
+ ConnectPoint connectPoint = ConnectPointProtoTranslator.translate(request.getConnectPoint()).get();
+ getEgressLinksReply.Builder builder = getEgressLinksReply.newBuilder();
+ linkService.getEgressLinks(connectPoint).forEach(l -> {
+ builder.addLink(LinkProtoTranslator.translate(l));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getIngressLinks(getIngressLinksRequest request,
+ StreamObserver<getIngressLinksReply> responseObserver) {
+ ConnectPoint connectPoint = ConnectPointProtoTranslator.translate(request.getConnectPoint()).get();
+
+ getIngressLinksReply.Builder builder = getIngressLinksReply.newBuilder();
+ linkService.getIngressLinks(connectPoint).forEach(l -> {
+ builder.addLink(LinkProtoTranslator.translate(l));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getLinks(getLinksRequest request,
+ StreamObserver<getLinksReply> responseObserver) {
+ ConnectPoint connectPoint = ConnectPointProtoTranslator.translate(request.getConnectPoint()).get();
+
+ getLinksReply.Builder builder = getLinksReply.newBuilder();
+ linkService.getLinks(connectPoint).forEach(l -> {
+ builder.addLink(LinkProtoTranslator.translate(l));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+ }
+
+ public LinkServiceNBServerInternal getInnerClassInstance() {
+ if (innerClassInstance == null) {
+ innerClassInstance = new LinkServiceNBServerInternal();
+ }
+ return innerClassInstance;
+ }
+}
+
+
+
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/package-info.java
similarity index 92%
rename from incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
rename to incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/package-info.java
index 0814b10..51cb983 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/package-info.java
@@ -16,4 +16,4 @@
/**
* gRPC server implementations for northbound services.
*/
-package org.onosproject.grpc.nb.net.device;
+package org.onosproject.incubator.protobuf.services.nb;
diff --git a/incubator/protobuf/services/nb/src/main/proto/net/link/LinkServiceNb.proto b/incubator/protobuf/services/nb/src/main/proto/net/link/LinkServiceNb.proto
new file mode 100644
index 0000000..7a267b7
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/proto/net/link/LinkServiceNb.proto
@@ -0,0 +1,90 @@
+syntax="proto3";
+option java_package = "org.onosproject.grpc.nb.net.link";
+
+package nb.net.link;
+
+import "net/LinkProto.proto";
+import "net/ConnectPointProto.proto";
+
+message getLinkCountRequest {
+}
+
+message getLinkCountReply {
+ int32 link_count = 1;
+}
+
+message getActiveLinksRequest {
+}
+
+message getActiveLinksReply {
+ repeated .net.LinkProto link = 1;
+}
+
+message getDeviceLinksRequest {
+ string device_id = 1;
+}
+
+message getDeviceLinksReply {
+ repeated .net.LinkProto link = 1;
+}
+
+message getDeviceEgressLinksRequest {
+ string device_id = 1;
+}
+
+message getDeviceEgressLinksReply {
+ repeated .net.LinkProto link = 1;
+}
+
+message getDeviceIngressLinksRequest {
+ string device_id = 1;
+}
+
+message getDeviceIngressLinksReply {
+ repeated .net.LinkProto link = 1;
+}
+
+message getLinksRequest {
+ .net.ConnectPointProto connect_point = 1;
+}
+
+message getLinksReply {
+ repeated .net.LinkProto link = 1;
+}
+
+message getEgressLinksRequest {
+ .net.ConnectPointProto connect_point = 1;
+}
+
+message getEgressLinksReply {
+ repeated .net.LinkProto link = 1;
+}
+
+message getIngressLinksRequest {
+ .net.ConnectPointProto connect_point = 1;
+}
+
+message getIngressLinksReply {
+ repeated .net.LinkProto link = 1;
+}
+
+message getLinkRequest {
+ .net.ConnectPointProto src = 1;
+ .net.ConnectPointProto dst = 2;
+}
+
+message getLinkReply {
+ .net.LinkProto link = 1;
+}
+
+service LinkService {
+ rpc getLinkCount(getLinkCountRequest) returns(getLinkCountReply) {}
+ rpc getLinks(getLinksRequest) returns(getLinksReply) {}
+ rpc getActiveLinks(getActiveLinksRequest) returns(getActiveLinksReply) {}
+ rpc getDeviceLinks(getDeviceLinksRequest) returns(getDeviceLinksReply) {}
+ rpc getDeviceEgressLinks(getDeviceEgressLinksRequest) returns(getDeviceEgressLinksReply) {}
+ rpc getDeviceIngressLinks(getDeviceIngressLinksRequest) returns(getDeviceIngressLinksReply) {}
+ rpc getEgressLinks(getEgressLinksRequest) returns(getEgressLinksReply) {}
+ rpc getIngressLinks(getIngressLinksRequest) returns(getIngressLinksReply) {}
+ rpc getLink(getLinkRequest) returns(getLinkReply) {}
+}
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkServiceTest.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkServiceTest.java
new file mode 100644
index 0000000..d734e50
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkServiceTest.java
@@ -0,0 +1,452 @@
+/*
+* 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.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.grpc.net.models.LinkProtoOuterClass;
+
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.PortNumber.portNumber;
+
+import io.grpc.ManagedChannel;
+import io.grpc.inprocess.InProcessChannelBuilder;
+import org.onosproject.incubator.protobuf.models.net.ConnectPointProtoTranslator;
+import org.onosproject.incubator.protobuf.models.net.LinkProtoTranslator;
+import org.onosproject.net.ConnectPoint;
+
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DeviceId;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.provider.ProviderId;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import org.onosproject.grpc.nb.net.link.LinkServiceGrpc;
+import org.onosproject.grpc.nb.net.link.LinkServiceGrpc.LinkServiceBlockingStub;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb;
+import org.onosproject.incubator.protobuf.services.nb.GrpcNbLinkService.LinkServiceNBServerInternal;
+
+public class GrpcNbLinkServiceTest {
+ private static InProcessServer<LinkServiceNBServerInternal> inprocessServer;
+ private static ManagedChannel channel;
+ private static LinkServiceBlockingStub blockingStub;
+
+ private static final String D1 = "d1";
+ private static final String D2 = "d2";
+ private static final String D3 = "d3";
+ private static final String D4 = "d4";
+ private static final String D5 = "d5";
+ private static final String D6 = "d6";
+ private static final String D7 = "d7";
+ private static final String D8 = "d8";
+ private static final String D9 = "d9";
+
+ private static final String[][] LINK_CONNECT_DATA = {
+ {D1, "12", D2, "21"},
+ {D2, "23", D3, "32"},
+ {D4, "41", D1, "14"},
+ {D5, "51", D1, "15"},
+ {D6, "61", D1, "16"},
+ {D7, "73", D3, "37"},
+ {D8, "83", D3, "38"},
+ {D9, "93", D3, "39"},
+ };
+
+ private static final DeviceId DEVID_1 = deviceId(D1);
+ private static final PortNumber PORT_14 = portNumber("14");
+
+ private static final DeviceId DEVID_4 = deviceId(D4);
+ private static final PortNumber PORT_41 = portNumber("41");
+
+ private static final DeviceId DEVID_3 = deviceId(D3);
+ private static final PortNumber PORT_32 = portNumber("32");
+
+ private static final ConnectPoint DEVID_1_14 = new ConnectPoint(DEVID_1, PORT_14);
+ private static final ConnectPoint DEVID_4_41 = new ConnectPoint(DEVID_4, PORT_41);
+
+ private static final ProviderId PID = new ProviderId("Test", "Test");
+
+ private static List<Link> allLinks = new ArrayList<Link>();
+
+ private static final LinkService MOCK_LINK = new MockLinkService();
+
+ /**
+ * Creates a list of links.
+ *
+ */
+ private static void populateLinks() {
+ for (String[] linkPair : LINK_CONNECT_DATA) {
+ allLinks.addAll(makeLinkPair(linkPair));
+ }
+ }
+
+ /**
+ * Synthesizes a pair of unidirectional links between two devices. The
+ * string array should be of the form:
+ * <pre>
+ * { "device-A-id", "device-A-port", "device-B-id", "device-B-port" }
+ * </pre>
+ *
+ * @param linkPairData device ids and ports
+ * @return pair of synthesized links
+ */
+ private static List<Link> makeLinkPair(String[] linkPairData) {
+ DeviceId devA = deviceId(linkPairData[0]);
+ PortNumber portA = portNumber(linkPairData[1]);
+
+ DeviceId devB = deviceId(linkPairData[2]);
+ PortNumber portB = portNumber(linkPairData[3]);
+
+ Link linkA = DefaultLink.builder()
+ .providerId(PID)
+ .type(Link.Type.DIRECT)
+ .src(new ConnectPoint(devA, portA))
+ .dst(new ConnectPoint(devB, portB))
+ .build();
+
+ Link linkB = DefaultLink.builder()
+ .providerId(PID)
+ .type(Link.Type.DIRECT)
+ .src(new ConnectPoint(devB, portB))
+ .dst(new ConnectPoint(devA, portA))
+ .build();
+
+ return ImmutableList.of(linkA, linkB);
+ }
+
+ public GrpcNbLinkServiceTest() {
+ }
+
+ @Test
+ public void testGetLinkCount() throws InterruptedException {
+ LinkServiceNb.getLinkCountRequest request = LinkServiceNb.getLinkCountRequest.getDefaultInstance();
+ LinkServiceNb.getLinkCountReply response;
+
+ try {
+ response = blockingStub.getLinkCount(request);
+ int linkCount = response.getLinkCount();
+ assertTrue(allLinks.size() == linkCount);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetLink() throws InterruptedException {
+ LinkServiceNb.getLinkRequest request = LinkServiceNb.getLinkRequest.newBuilder()
+ .setSrc(ConnectPointProtoTranslator.translate(DEVID_1_14))
+ .setDst(ConnectPointProtoTranslator.translate(DEVID_4_41))
+ .build();
+ LinkServiceNb.getLinkReply response;
+
+ try {
+ response = blockingStub.getLink(request);
+ LinkProtoOuterClass.LinkProto link = response.getLink();
+ assertTrue(LinkProtoTranslator.translate(allLinks.get(5)).equals(link));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetLinks() throws InterruptedException {
+ LinkServiceNb.getLinksRequest request = LinkServiceNb.getLinksRequest.newBuilder()
+ .setConnectPoint(ConnectPointProtoTranslator.translate(DEVID_1_14))
+ .build();
+ LinkServiceNb.getLinksReply response;
+
+ try {
+ response = blockingStub.getLinks(request);
+
+ Set<Link> actualLinks = new HashSet<Link>();
+ for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+ actualLinks.add(LinkProtoTranslator.translate(link));
+ }
+ Set<Link> expectedLinks = new HashSet<Link>();
+ expectedLinks.add(allLinks.get(4));
+ expectedLinks.add(allLinks.get(5));
+
+ assertTrue(expectedLinks.equals(actualLinks));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetActiveLinks() throws InterruptedException {
+ LinkServiceNb.getActiveLinksRequest request = LinkServiceNb.getActiveLinksRequest.getDefaultInstance();
+ LinkServiceNb.getActiveLinksReply response;
+
+ try {
+ response = blockingStub.getActiveLinks(request);
+
+ Set<Link> actualLinks = new HashSet<Link>();
+ for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+ actualLinks.add(LinkProtoTranslator.translate(link));
+ }
+
+ Set<Link> expectedLinks = new HashSet<Link>(allLinks);
+ assertTrue((expectedLinks).equals(actualLinks));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetDeviceLinks() throws InterruptedException {
+ LinkServiceNb.getDeviceLinksRequest request = LinkServiceNb.getDeviceLinksRequest.newBuilder()
+ .setDeviceId(D1)
+ .build();
+ LinkServiceNb.getDeviceLinksReply response;
+
+ try {
+ response = blockingStub.getDeviceLinks(request);
+
+ Set<Link> actualLinks = new HashSet<Link>();
+ for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+ actualLinks.add(LinkProtoTranslator.translate(link));
+ }
+
+ Set<Link> expectedLinks = new HashSet<Link>();
+ expectedLinks.add(allLinks.get(4));
+ expectedLinks.add(allLinks.get(5));
+ expectedLinks.add(allLinks.get(6));
+ expectedLinks.add(allLinks.get(7));
+ expectedLinks.add(allLinks.get(8));
+ expectedLinks.add(allLinks.get(9));
+ expectedLinks.add(allLinks.get(0));
+ expectedLinks.add(allLinks.get(1));
+
+ assertTrue((expectedLinks).equals(actualLinks));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetDeviceEgressLinks() throws InterruptedException {
+ LinkServiceNb.getDeviceEgressLinksRequest request = LinkServiceNb.getDeviceEgressLinksRequest.newBuilder()
+ .setDeviceId(D1)
+ .build();
+ LinkServiceNb.getDeviceEgressLinksReply response;
+
+ try {
+ response = blockingStub.getDeviceEgressLinks(request);
+
+ Set<Link> actualLinks = new HashSet<Link>();
+ for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+ actualLinks.add(LinkProtoTranslator.translate(link));
+ }
+ Set<Link> expectedLinks = new HashSet<Link>();
+ expectedLinks.add(allLinks.get(0));
+ expectedLinks.add(allLinks.get(5));
+ expectedLinks.add(allLinks.get(7));
+ expectedLinks.add(allLinks.get(9));
+
+ assertTrue((expectedLinks).equals(actualLinks));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetDeviceIngressLinks() throws InterruptedException {
+ LinkServiceNb.getDeviceIngressLinksRequest request = LinkServiceNb.getDeviceIngressLinksRequest.newBuilder()
+ .setDeviceId(D1)
+ .build();
+ LinkServiceNb.getDeviceIngressLinksReply response;
+
+ try {
+ response = blockingStub.getDeviceIngressLinks(request);
+
+ Set<Link> actualLinks = new HashSet<Link>();
+ for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+ actualLinks.add(LinkProtoTranslator.translate(link));
+ }
+
+ Set<Link> expectedLinks = new HashSet<Link>();
+ expectedLinks.add(allLinks.get(1));
+ expectedLinks.add(allLinks.get(4));
+ expectedLinks.add(allLinks.get(6));
+ expectedLinks.add(allLinks.get(8));
+
+ assertTrue((expectedLinks).equals(actualLinks));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetEgressLinks() throws InterruptedException {
+ LinkServiceNb.getEgressLinksRequest request = LinkServiceNb.getEgressLinksRequest.newBuilder()
+ .setConnectPoint(ConnectPointProtoTranslator.translate(DEVID_1_14))
+ .build();
+ LinkServiceNb.getEgressLinksReply response;
+
+ try {
+ response = blockingStub.getEgressLinks(request);
+
+ Set<Link> actualLinks = new HashSet<Link>();
+ for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+ actualLinks.add(LinkProtoTranslator.translate(link));
+ }
+ Set<Link> expectedLinks = new HashSet<Link>();
+ expectedLinks.add(allLinks.get(5));
+
+ assertTrue((expectedLinks).equals(actualLinks));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetIngressLinks() throws InterruptedException {
+ LinkServiceNb.getIngressLinksRequest request = LinkServiceNb.getIngressLinksRequest.newBuilder()
+ .setConnectPoint(ConnectPointProtoTranslator.translate(DEVID_1_14))
+ .build();
+ LinkServiceNb.getIngressLinksReply response;
+
+ try {
+ response = blockingStub.getIngressLinks(request);
+
+ Set<Link> actualLinks = new HashSet<Link>();
+ for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+ actualLinks.add(LinkProtoTranslator.translate(link));
+ }
+ Set<Link> expectedLinks = new HashSet<Link>();
+ expectedLinks.add(allLinks.get(4));
+
+ assertTrue((expectedLinks).equals(actualLinks));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @BeforeClass
+ public static void beforeClass() throws InstantiationException, IllegalAccessException, IOException {
+ inprocessServer = new InProcessServer<LinkServiceNBServerInternal>(LinkServiceNBServerInternal.class);
+
+ GrpcNbLinkService outer = new GrpcNbLinkService();
+ GrpcNbLinkService.LinkServiceNBServerInternal inner = outer.getInnerClassInstance();
+ outer.linkService = MOCK_LINK;
+ inprocessServer.addServiceToBind(inner);
+
+ 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 = LinkServiceGrpc.newBlockingStub(channel);
+
+ populateLinks();
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ channel.shutdownNow();
+
+ inprocessServer.stop();
+ }
+
+ private static class MockLinkService implements LinkService {
+ MockLinkService() {
+ }
+
+ @Override
+ public int getLinkCount() {
+ return allLinks.size();
+ }
+
+ @Override
+ public Iterable<Link> getLinks() {
+ return ImmutableSet.copyOf(allLinks);
+ }
+
+ @Override
+ public Iterable<Link> getActiveLinks() {
+ return FluentIterable.from(getLinks())
+ .filter(input -> input.state() == Link.State.ACTIVE);
+ }
+
+ @Override
+ public Set<Link> getDeviceLinks(DeviceId deviceId) {
+ return FluentIterable.from(getLinks())
+ .filter(input -> (input.src().deviceId().equals(deviceId)) ||
+ (input.dst().deviceId().equals(deviceId))).toSet();
+ }
+
+ @Override
+ public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
+ return FluentIterable.from(getLinks())
+ .filter(input -> (input.src().deviceId().equals(deviceId))).toSet();
+ }
+
+ @Override
+ public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
+ return FluentIterable.from(getLinks())
+ .filter(input -> (input.dst().deviceId().equals(deviceId))).toSet();
+ }
+
+ @Override
+ public Set<Link> getLinks(ConnectPoint connectPoint) {
+ return FluentIterable.from(getLinks())
+ .filter(input -> (input.src().equals(connectPoint)) || (input.dst().equals(connectPoint))).toSet();
+ }
+
+ @Override
+ public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
+ return FluentIterable.from(getLinks())
+ .filter(input -> (input.src().equals(connectPoint))).toSet();
+ }
+
+ @Override
+ public Set<Link> getIngressLinks(ConnectPoint connectPoint) {
+ return FluentIterable.from(getLinks())
+ .filter(input -> (input.dst().equals(connectPoint))).toSet();
+ }
+
+ @Override
+ public Link getLink(ConnectPoint src, ConnectPoint dst) {
+ return FluentIterable.from(getLinks())
+ .filter(input -> (input.src().equals(src)) && (input.dst().equals(dst)))
+ .first().get();
+ }
+
+ @Override
+ public void addListener(org.onosproject.net.link.LinkListener listener) {
+ }
+
+ @Override
+ public void removeListener(org.onosproject.net.link.LinkListener listener) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/InProcessServer.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/InProcessServer.java
new file mode 100644
index 0000000..6caa9d9
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/InProcessServer.java
@@ -0,0 +1,78 @@
+/*
+* 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.Sets;
+import io.grpc.Server;
+import io.grpc.inprocess.InProcessServerBuilder;
+import io.grpc.internal.AbstractServerImplBuilder;
+
+import java.io.IOException;
+import java.util.Set;
+/**
+ * InProcessServer that manages startup/shutdown of a service within the same process
+ * as the client is running. Used for unit testing purposes.
+ */
+public class InProcessServer<T extends io.grpc.BindableService> {
+ private Server server;
+
+ Set<T> services = Sets.newHashSet();
+
+ private Class<T> clazz;
+
+ public InProcessServer(Class<T> clazz) {
+ this.clazz = clazz;
+ }
+
+ public void addServiceToBind(T service) {
+ if (service != null) {
+ services.add(service);
+ }
+ }
+
+ public void start() throws IOException, InstantiationException, IllegalAccessException {
+
+ AbstractServerImplBuilder builder = InProcessServerBuilder.forName("test").directExecutor();
+ services.forEach(service -> builder.addService(service));
+ server = builder.build().start();
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ // Use stderr here since the logger may have been reset by its JVM shutdown hook.
+ System.err.println("*** shutting down gRPC server since JVM is shutting down");
+ InProcessServer.this.stop();
+ System.err.println("*** server shut down");
+ }
+ });
+ }
+
+ void stop() {
+ if (server != null) {
+ server.shutdown();
+ }
+ }
+
+ /**
+ * Await termination on the main thread since the grpc library uses daemon threads.
+ * @throws InterruptedException if there is an issue
+ */
+ public void blockUntilShutdown() throws InterruptedException {
+ if (server != null) {
+ server.awaitTermination();
+ }
+ }
+}
\ No newline at end of file