Created RegionService and added unit tests.
Change-Id: If3735d160ead9269b8bb327a99d6dad85e5c57d0
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/RegionProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/RegionProtoTranslator.java
new file mode 100644
index 0000000..5baea7a
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/RegionProtoTranslator.java
@@ -0,0 +1,94 @@
+/*
+ * 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 com.google.common.base.Strings;
+import org.onosproject.incubator.protobuf.models.ProtobufUtils;
+import org.onosproject.incubator.protobuf.models.net.region.RegionEnumsProtoTranslator;
+
+
+
+import org.onosproject.cluster.NodeId;
+import org.onosproject.grpc.net.models.RegionProtoOuterClass;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.region.DefaultRegion;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionId;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * gRPC Region message to @link org.onosproject.net.region.Region conversion related utilities for region service.
+ */
+public final class RegionProtoTranslator {
+
+ /**
+ * Translates gRPC RegionProto message to {@link org.onosproject.net.region.Region}.
+ *
+ * @param region gRPC message
+ * @return {@link org.onosproject.net.region.Region}
+ */
+ public static Region translate(RegionProtoOuterClass.RegionProto region) {
+ RegionId id = RegionId.regionId(region.getRegionId());
+ Region.Type type = RegionEnumsProtoTranslator.translate(region.getType()).get();
+ String name = Strings.nullToEmpty(region.getName());
+
+ List<Set<NodeId>> masters = new ArrayList<>();
+
+ region.getMastersList().forEach(s -> {
+ Set<NodeId> nodeIdSet = new HashSet<NodeId>();
+ s.getNodeIdList().forEach(n -> {
+ nodeIdSet.add(new NodeId(n));
+ });
+ masters.add(nodeIdSet);
+ });
+
+ Annotations annots = ProtobufUtils.asAnnotations(region.getAnnotations());
+
+ return new DefaultRegion(id, name, type, annots, masters);
+ }
+
+ /**
+ * Translates {@link org.onosproject.net.region.Region} to gRPC RegionProto message.
+ *
+ * @param region {@link org.onosproject.net.region.Region}
+ * @return gRPC RegionProto message
+ */
+ public static RegionProtoOuterClass.RegionProto translate(Region region) {
+ return RegionProtoOuterClass.RegionProto.newBuilder()
+ .setRegionId(region.id().toString())
+ .setType(RegionEnumsProtoTranslator.translate(region.type()))
+ .setName(region.name().isEmpty() ? null : region.name())
+ .addAllMasters(region.masters()
+ .stream()
+ .map(s -> RegionProtoOuterClass.RegionProto.NodeIdSet
+ .newBuilder()
+ .addAllNodeId(s.stream().map(id -> {
+ return id.toString();
+ }).collect(Collectors.toList()))
+ .build())
+ .collect(Collectors.toList()))
+ .build();
+ }
+
+ // Utility class not intended for instantiation.
+ private RegionProtoTranslator() {}
+
+}
+
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/RegionEnumsProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/RegionEnumsProtoTranslator.java
new file mode 100644
index 0000000..6f3130f
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/RegionEnumsProtoTranslator.java
@@ -0,0 +1,104 @@
+/*
+ * 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.region;
+
+import org.onosproject.grpc.net.region.models.RegionEnumsProto;
+import org.onosproject.net.region.Region;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+/**
+ * gRPC RegionType message to equivalent ONOS enum conversion related utilities.
+ */
+public final class RegionEnumsProtoTranslator {
+
+ private static final Logger log = LoggerFactory.getLogger(RegionEnumsProtoTranslator.class);
+
+ /**
+ * Translates gRPC enum RegionType to Optional of ONOS enum.
+ *
+ * @param type regiontype type in gRPC enum
+ * @return Optional of equivalent ONOS enum or empty if not recognized
+ */
+ public static Optional<Region.Type> translate(RegionEnumsProto.RegionTypeProto type) {
+ switch (type) {
+ case CONTINENT:
+ return Optional.of(Region.Type.CONTINENT);
+ case COUNTRY:
+ return Optional.of(Region.Type.COUNTRY);
+ case METRO:
+ return Optional.of(Region.Type.METRO);
+ case CAMPUS:
+ return Optional.of(Region.Type.CAMPUS);
+ case BUILDING:
+ return Optional.of(Region.Type.BUILDING);
+ case DATA_CENTER:
+ return Optional.of(Region.Type.DATA_CENTER);
+ case FLOOR:
+ return Optional.of(Region.Type.FLOOR);
+ case ROOM:
+ return Optional.of(Region.Type.ROOM);
+ case RACK:
+ return Optional.of(Region.Type.RACK);
+ case LOGICAL_GROUP:
+ return Optional.of(Region.Type.LOGICAL_GROUP);
+ default:
+ log.warn("Unrecognized Type gRPC message: {}", type);
+ return Optional.empty();
+ }
+ }
+
+
+ /**
+ * Translates ONOS enum regionType to gRPC enum regionType.
+ *
+ * @param type ONOS' Type type
+ * @return equivalent gRPC message enum
+ */
+ public static RegionEnumsProto.RegionTypeProto translate(Region.Type type) {
+ switch (type) {
+ case CONTINENT:
+ return RegionEnumsProto.RegionTypeProto.CONTINENT;
+ case COUNTRY:
+ return RegionEnumsProto.RegionTypeProto.COUNTRY;
+ case METRO:
+ return RegionEnumsProto.RegionTypeProto.METRO;
+ case CAMPUS:
+ return RegionEnumsProto.RegionTypeProto.CAMPUS;
+ case BUILDING:
+ return RegionEnumsProto.RegionTypeProto.BUILDING;
+ case DATA_CENTER:
+ return RegionEnumsProto.RegionTypeProto.DATA_CENTER;
+ case FLOOR:
+ return RegionEnumsProto.RegionTypeProto.FLOOR;
+ case ROOM:
+ return RegionEnumsProto.RegionTypeProto.ROOM;
+ case RACK:
+ return RegionEnumsProto.RegionTypeProto.RACK;
+ case LOGICAL_GROUP:
+ return RegionEnumsProto.RegionTypeProto.LOGICAL_GROUP;
+ default:
+ log.warn("Unrecognized type", type);
+ throw new IllegalArgumentException("Unrecognized Type");
+ }
+ }
+
+ // Utility class not intended for instantiation.
+ private RegionEnumsProtoTranslator() {}
+}
+
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/package-info.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/package-info.java
new file mode 100644
index 0000000..459ad32
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/region/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+/**
+ * Utilities to handle ProtoBuf version of ONOS region models.
+ */
+package org.onosproject.incubator.protobuf.models.net.region;
diff --git a/incubator/protobuf/models/src/main/proto/net/RegionProto.proto b/incubator/protobuf/models/src/main/proto/net/RegionProto.proto
new file mode 100644
index 0000000..359008f
--- /dev/null
+++ b/incubator/protobuf/models/src/main/proto/net/RegionProto.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+option java_package = "org.onosproject.grpc.net.models";
+
+package net;
+
+import "net/region/RegionEnumsProto.proto";
+
+// Corresponds to org.onosproject.net.Region.
+
+message RegionProto {
+ string region_id = 1;
+ net.region.RegionTypeProto type = 2;
+ string name = 3;
+
+ // List<Set<NodeId>> masters();
+ // Since masters is a list of set of NodeIds,
+ // the following message is required.
+ message NodeIdSet {
+ repeated string node_id = 1;
+ }
+
+ repeated NodeIdSet masters = 4;
+ map<string, string> annotations = 5;
+}
\ No newline at end of file
diff --git a/incubator/protobuf/models/src/main/proto/net/region/RegionEnumsProto.proto b/incubator/protobuf/models/src/main/proto/net/region/RegionEnumsProto.proto
new file mode 100644
index 0000000..c7b449d
--- /dev/null
+++ b/incubator/protobuf/models/src/main/proto/net/region/RegionEnumsProto.proto
@@ -0,0 +1,56 @@
+syntax = "proto3";
+option java_package = "org.onosproject.grpc.net.region.models";
+
+package net.region;
+
+enum RegionTypeProto {
+ /**
+ * Region represents an entire continent.
+ */
+ CONTINENT = 0;
+
+ /**
+ * Region represents an entire country.
+ */
+ COUNTRY = 1;
+
+ /**
+ * Region represents a metropolitan area.
+ */
+ METRO = 2;
+
+ /**
+ * Region represents a campus.
+ */
+ CAMPUS = 3;
+
+ /**
+ * Region represents a building.
+ */
+ BUILDING = 4;
+
+ /**
+ * Region represents a data center.
+ */
+ DATA_CENTER = 5;
+
+ /**
+ * Region represents a building floor.
+ */
+ FLOOR = 6;
+
+ /**
+ * Region represents a room.
+ */
+ ROOM = 7;
+
+ /**
+ * Region represents a rack.
+ */
+ RACK = 8;
+
+ /**
+ * Region represents a logical grouping.
+ */
+ LOGICAL_GROUP = 9;
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
index 0ba9e48..4ca0e03 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.grpc.nb.net.device;
+package org.onosproject.incubator.protobuf.services.nb;
import com.google.common.annotations.Beta;
@@ -84,7 +84,7 @@
@Override
public void getDeviceCount(
getDeviceCountRequest request,
- StreamObserver<DeviceServiceNb.getDeviceCountReply> responseObserver) {
+ StreamObserver<getDeviceCountReply> responseObserver) {
responseObserver
.onNext(getDeviceCountReply
.newBuilder()
@@ -97,7 +97,7 @@
//FIXME NOTE: this will be switched to a streaming version.
@Override
public void getDevices(getDevicesRequest request,
- StreamObserver<DeviceServiceNb.getDevicesReply> responseObserver) {
+ StreamObserver<getDevicesReply> responseObserver) {
getDevicesReply.Builder replyBuilder = getDevicesReply.newBuilder();
deviceService.getDevices().forEach(d -> {
replyBuilder.addDevice(
@@ -122,7 +122,7 @@
@Override
public void getAvailableDevices(getAvailableDevicesRequest request,
StreamObserver
- <DeviceServiceNb.getAvailableDevicesReply> responseObserver) {
+ <getAvailableDevicesReply> responseObserver) {
getAvailableDevicesReply.Builder replyBuilder = getAvailableDevicesReply.newBuilder();
deviceService.getAvailableDevices().forEach(d -> {
replyBuilder.addDevice(
@@ -144,7 +144,7 @@
@Override
public void getDevice(getDeviceRequest request,
- io.grpc.stub.StreamObserver<DeviceServiceNb.getDeviceReply> responseObserver) {
+ io.grpc.stub.StreamObserver<getDeviceReply> responseObserver) {
org.onosproject.net.Device device = deviceService.getDevice(
DeviceId.deviceId(request.getDeviceId()));
responseObserver.onNext(
@@ -166,7 +166,7 @@
@Override
public void getRole(getRoleRequest request,
- StreamObserver<DeviceServiceNb.getRoleReply> responseObserver) {
+ StreamObserver<getRoleReply> responseObserver) {
DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
MastershipRole role = deviceService.getRole(deviceId);
DeviceEnumsProto.MastershipRoleProto mastershipRole =
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionService.java
new file mode 100644
index 0000000..744941f
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionService.java
@@ -0,0 +1,169 @@
+/*
+* 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.RegionProtoTranslator;
+
+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.region.RegionServiceGrpc.RegionServiceImplBase;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.region.RegionId;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionService;
+
+
+import java.io.IOException;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionsRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionsReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionForDeviceRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionForDeviceReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionDevicesRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionDevicesReply;
+
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionHostsRequest;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb.getRegionHostsReply;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * A server that provides access to the methods exposed by {@link RegionService}.
+ */
+@Beta
+@Component(immediate = true)
+public class GrpcNbRegionService {
+
+ private Server server;
+ private final Logger log = getLogger(getClass());
+ private RegionServiceNBServerInternal innerClassInstance = null;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected RegionService regionService;
+
+ @Activate
+ public void activate() {
+ server = ServerBuilder.forPort(64000).addService(new RegionServiceNBServerInternal()).build();
+ try {
+ server.start();
+ } catch (IOException e) {
+ log.error("Failed to start server", e);
+ throw new RuntimeException("Failed to start server", e);
+ }
+ }
+
+ @Deactivate
+ public void deactivate() {
+ server.shutdown();
+ }
+
+ public class RegionServiceNBServerInternal extends RegionServiceImplBase {
+ /**
+ * Service for interacting with inventory of network control regions.
+ */
+ @Override
+ public void getRegions(getRegionsRequest request,
+ StreamObserver<getRegionsReply> responseObserver) {
+ getRegionsReply.Builder builder = getRegionsReply.newBuilder();
+ regionService.getRegions().forEach(r -> {
+ builder.addRegion(RegionProtoTranslator.translate(r));
+ });
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getRegion(getRegionRequest request,
+ StreamObserver<getRegionReply> responseObserver) {
+ RegionId regionId = RegionId.regionId(request.getRegionId());
+ Region region = regionService.getRegion(regionId);
+
+ getRegionReply reply = getRegionReply.newBuilder()
+ .setRegion(RegionProtoTranslator.translate(region)).build();
+
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getRegionForDevice(getRegionForDeviceRequest request,
+ StreamObserver<getRegionForDeviceReply> responseObserver) {
+ DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+ Region region = regionService.getRegionForDevice(deviceId);
+
+ getRegionForDeviceReply reply = getRegionForDeviceReply.newBuilder()
+ .setRegion(RegionProtoTranslator.translate(region)).build();
+
+ responseObserver.onNext(reply);
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getRegionDevices(getRegionDevicesRequest request,
+ StreamObserver<getRegionDevicesReply> responseObserver) {
+ RegionId regionId = RegionId.regionId(request.getRegionId());
+ getRegionDevicesReply.Builder builder = getRegionDevicesReply.newBuilder();
+
+ regionService.getRegionDevices(regionId).forEach(d -> {
+ builder.addDeviceId(d.toString());
+ });
+
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void getRegionHosts(getRegionHostsRequest request,
+ StreamObserver<getRegionHostsReply> responseObserver) {
+ RegionId regionId = RegionId.regionId(request.getRegionId());
+ getRegionHostsReply.Builder builder = getRegionHostsReply.newBuilder();
+
+ regionService.getRegionHosts(regionId).forEach(h -> {
+ builder.addHostId(h.toString());
+ });
+
+ responseObserver.onNext(builder.build());
+ responseObserver.onCompleted();
+ }
+ }
+
+ public RegionServiceNBServerInternal getInnerClassInstance() {
+ if (innerClassInstance == null) {
+ innerClassInstance = new RegionServiceNBServerInternal();
+ }
+ return innerClassInstance;
+ }
+}
+
+
+
+
+
+
+
diff --git a/incubator/protobuf/services/nb/src/main/proto/net/region/RegionServiceNb.proto b/incubator/protobuf/services/nb/src/main/proto/net/region/RegionServiceNb.proto
new file mode 100644
index 0000000..5498b33
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/proto/net/region/RegionServiceNb.proto
@@ -0,0 +1,53 @@
+syntax="proto3";
+option java_package = "org.onosproject.grpc.nb.net.region";
+
+package nb.net.region;
+
+import "net/RegionProto.proto";
+
+message getRegionsRequest {
+}
+
+message getRegionsReply {
+ repeated .net.RegionProto region = 1;
+}
+
+message getRegionRequest {
+ string regionId = 1;
+}
+
+message getRegionReply {
+ .net.RegionProto region = 1;
+}
+
+message getRegionForDeviceRequest {
+ string deviceId = 1;
+}
+
+message getRegionForDeviceReply {
+ .net.RegionProto region = 1;
+}
+
+message getRegionDevicesRequest {
+ string regionId = 1;
+}
+
+message getRegionDevicesReply {
+ repeated string deviceId = 1;
+}
+
+message getRegionHostsRequest {
+ string regionId = 1;
+}
+
+message getRegionHostsReply {
+ repeated string hostId = 1;
+}
+
+service RegionService {
+ rpc getRegions(getRegionsRequest) returns (getRegionsReply) {}
+ rpc getRegion(getRegionRequest) returns (getRegionReply) {}
+ rpc getRegionForDevice(getRegionForDeviceRequest) returns (getRegionForDeviceReply) {}
+ rpc getRegionDevices(getRegionDevicesRequest) returns (getRegionDevicesReply) {}
+ rpc getRegionHosts(getRegionHostsRequest) returns (getRegionHostsReply) {}
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionServiceTest.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionServiceTest.java
new file mode 100644
index 0000000..7b93d8e
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbRegionServiceTest.java
@@ -0,0 +1,382 @@
+/*
+* 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 com.google.common.collect.ImmutableList;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.grpc.net.models.RegionProtoOuterClass;
+
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.cluster.NodeId.nodeId;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.HostId.hostId;
+
+import io.grpc.ManagedChannel;
+import io.grpc.inprocess.InProcessChannelBuilder;
+import org.onosproject.net.DefaultAnnotations;
+
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+
+import org.onosproject.net.HostId;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.net.region.DefaultRegion;
+import org.onosproject.net.region.RegionListener;
+import org.onosproject.net.region.RegionService;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+
+import org.onosproject.incubator.protobuf.models.net.RegionProtoTranslator;
+import org.onosproject.grpc.nb.net.region.RegionServiceGrpc;
+import org.onosproject.grpc.nb.net.region.RegionServiceGrpc.RegionServiceBlockingStub;
+import org.onosproject.grpc.nb.net.region.RegionServiceNb;
+import org.onosproject.incubator.protobuf.services.nb.GrpcNbRegionService.RegionServiceNBServerInternal;
+import org.onosproject.net.region.Region;
+import org.onosproject.net.region.RegionId;
+
+public class GrpcNbRegionServiceTest {
+ private static InProcessServer<GrpcNbRegionService.RegionServiceNBServerInternal> inprocessServer;
+ private static ManagedChannel channel;
+ private static RegionServiceBlockingStub blockingStub;
+
+ private static final String C1 = "C1";
+ private static final String C2 = "C2";
+ private static final String C3 = "C3";
+
+ private static final NodeId CNID_1 = nodeId(C1);
+ private static final NodeId CNID_2 = nodeId(C2);
+ private static final NodeId CNID_3 = nodeId(C3);
+
+ private static final String R1 = "R1";
+ private static final String R2 = "R2";
+ private static final String R3 = "R3";
+
+ private static final Set<NodeId> SET_C1 = ImmutableSet.of(CNID_1);
+ private static final Set<NodeId> SET_C2 = ImmutableSet.of(CNID_2);
+ private static final Set<NodeId> SET_C3 = ImmutableSet.of(CNID_3);
+
+ private static final Region REGION_1 =
+ region(R1, Region.Type.METRO, ImmutableList.of(SET_C1, SET_C2));
+ private static final Region REGION_2 =
+ region(R2, Region.Type.CAMPUS, ImmutableList.of(SET_C2, SET_C1));
+ private static final Region REGION_3 =
+ region(R3, Region.Type.CAMPUS, ImmutableList.of(SET_C3, SET_C1));
+
+ private static final Set<Region> REGION_SET =
+ ImmutableSet.of(REGION_1, REGION_2, REGION_3);
+
+ 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 MFR = "Mfr";
+ private static final String HW = "h/w";
+ private static final String SW = "s/w";
+ private static final String SERIAL = "ser123";
+
+ private static final DeviceId DEVID_1 = deviceId(D1);
+ private static final DeviceId DEVID_2 = deviceId(D2);
+ private static final DeviceId DEVID_3 = deviceId(D3);
+ private static final DeviceId DEVID_4 = deviceId(D4);
+ private static final DeviceId DEVID_5 = deviceId(D5);
+ private static final DeviceId DEVID_6 = deviceId(D6);
+ private static final DeviceId DEVID_7 = deviceId(D7);
+ private static final DeviceId DEVID_8 = deviceId(D8);
+ private static final DeviceId DEVID_9 = deviceId(D9);
+
+ private static final Set<DeviceId> DEVS_TRUNK =
+ ImmutableSet.of(DEVID_1, DEVID_2, DEVID_3);
+
+ private static final Set<DeviceId> DEVS_LEFT =
+ ImmutableSet.of(DEVID_4, DEVID_5, DEVID_6);
+
+ private static final Set<DeviceId> DEVS_RIGHT =
+ ImmutableSet.of(DEVID_7, DEVID_8, DEVID_9);
+
+ private static final String[][] HOST_DATA = {
+ {"AA:00:00:00:00:1A/None", R1},
+ {"AA:00:00:00:00:1B/None", R1},
+ {"AA:00:00:00:00:2A/None", R1},
+ {"AA:00:00:00:00:2B/None", R1},
+ {"AA:00:00:00:00:3A/None", R1},
+ {"AA:00:00:00:00:3B/None", R1},
+ {"AA:00:00:00:00:4A/None", R2},
+ {"AA:00:00:00:00:4B/None", R2},
+ {"AA:00:00:00:00:5A/None", R2},
+ {"AA:00:00:00:00:5B/None", R2},
+ {"AA:00:00:00:00:6A/None", R2},
+ {"AA:00:00:00:00:6B/None", R2},
+ {"AA:00:00:00:00:7A/None", R3},
+ {"AA:00:00:00:00:7B/None", R3},
+ {"AA:00:00:00:00:8A/None", R3},
+ {"AA:00:00:00:00:8B/None", R3},
+ {"AA:00:00:00:00:9A/None", R3},
+ {"AA:00:00:00:00:9B/None", R3},
+ };
+
+ private static final Map<HostId, RegionId> HOSTS = new HashMap<>();
+ private static final RegionService MOCK_REGION = new MockRegionService();
+
+ /**
+ * Returns device with given ID.
+ *
+ * @param id device ID
+ * @return device instance
+ */
+ protected static Device device(String id) {
+ return new DefaultDevice(ProviderId.NONE, deviceId(id),
+ Device.Type.SWITCH, MFR, HW, SW, SERIAL, null);
+ }
+
+ /**
+ * Returns a region instance with specified parameters.
+ *
+ * @param id region id
+ * @param type region type
+ * @param masters ordered list of master sets
+ * @return region instance
+ */
+ private static Region region(String id, Region.Type type,
+ List<Set<NodeId>> masters) {
+ return new DefaultRegion(RegionId.regionId(id), "Region-" + id,
+ type, DefaultAnnotations.EMPTY, masters);
+ }
+
+ /**
+ * Creates a map of hostIds corresponding to their regionIds.
+ *
+ */
+ private static void populateHosts() {
+ for (String[] row : HOST_DATA) {
+ HOSTS.put(hostId(row[0]), RegionId.regionId(row[1]));
+ }
+ }
+
+ public GrpcNbRegionServiceTest() {
+ }
+
+ @Test
+ public void testGetRegion() throws InterruptedException {
+
+ RegionServiceNb.getRegionRequest request = RegionServiceNb.getRegionRequest.newBuilder()
+ .setRegionId(R1).build();
+ RegionServiceNb.getRegionReply response;
+
+ try {
+ response = blockingStub.getRegion(request);
+ Region actualRegion = RegionProtoTranslator.translate(response.getRegion());
+ assertTrue(REGION_1.equals(actualRegion));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetRegions() throws InterruptedException {
+
+ RegionServiceNb.getRegionsRequest request = RegionServiceNb.getRegionsRequest.newBuilder()
+ .build();
+ RegionServiceNb.getRegionsReply response;
+
+ try {
+ response = blockingStub.getRegions(request);
+ Set<Region> actualRegions = new HashSet<Region>();
+ for (RegionProtoOuterClass.RegionProto region : response.getRegionList()) {
+ actualRegions.add(RegionProtoTranslator.translate(region));
+ }
+ assertTrue(REGION_SET.equals(actualRegions));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetRegionForDevice() throws InterruptedException {
+
+ RegionServiceNb.getRegionForDeviceRequest request = RegionServiceNb.getRegionForDeviceRequest.newBuilder()
+ .setDeviceId(D1).build();
+ RegionServiceNb.getRegionForDeviceReply response;
+
+ try {
+ response = blockingStub.getRegionForDevice(request);
+ Region actualRegion = RegionProtoTranslator.translate(response.getRegion());
+ assertTrue(REGION_1.equals(actualRegion));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetRegionDevices() throws InterruptedException {
+
+ RegionServiceNb.getRegionDevicesRequest request = RegionServiceNb.getRegionDevicesRequest.newBuilder()
+ .setRegionId(R1).build();
+ RegionServiceNb.getRegionDevicesReply response;
+
+ try {
+ response = blockingStub.getRegionDevices(request);
+ Set<DeviceId> actualDevices = new HashSet<DeviceId>();
+ for (String deviceId : response.getDeviceIdList()) {
+ actualDevices.add(DeviceId.deviceId(deviceId));
+ }
+ assertTrue(DEVS_TRUNK.equals(actualDevices));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testGetRegionHosts() throws InterruptedException {
+ RegionServiceNb.getRegionHostsRequest request = RegionServiceNb.getRegionHostsRequest.newBuilder()
+ .setRegionId(R1).build();
+ RegionServiceNb.getRegionHostsReply response;
+
+ Set<HostId> expectedHosts = new HashSet<HostId>();
+
+ expectedHosts.add(HostId.hostId(HOST_DATA[0][0]));
+ expectedHosts.add(HostId.hostId(HOST_DATA[1][0]));
+ expectedHosts.add(HostId.hostId(HOST_DATA[2][0]));
+ expectedHosts.add(HostId.hostId(HOST_DATA[3][0]));
+ expectedHosts.add(HostId.hostId(HOST_DATA[4][0]));
+ expectedHosts.add(HostId.hostId(HOST_DATA[5][0]));
+
+ Set<HostId> actualHosts = new HashSet<HostId>();
+
+ try {
+ response = blockingStub.getRegionHosts(request);
+ for (String hostId : response.getHostIdList()) {
+ actualHosts.add(HostId.hostId(hostId));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ assertTrue(expectedHosts.equals(actualHosts));
+ }
+
+ @BeforeClass
+ public static void beforeClass() throws InstantiationException, IllegalAccessException, IOException {
+ inprocessServer = new InProcessServer<RegionServiceNBServerInternal>(RegionServiceNBServerInternal.class);
+
+ GrpcNbRegionService outer = new GrpcNbRegionService();
+ GrpcNbRegionService.RegionServiceNBServerInternal inner = outer.getInnerClassInstance();
+ outer.regionService = MOCK_REGION;
+ 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 = RegionServiceGrpc.newBlockingStub(channel);
+ populateHosts();
+ }
+
+ @AfterClass
+ public static void afterClass() {
+ channel.shutdownNow();
+
+ inprocessServer.stop();
+ }
+
+ private static class MockRegionService implements RegionService {
+
+ private final Map<RegionId, Region> lookup = new HashMap<>();
+
+ MockRegionService() {
+ lookup.put(REGION_1.id(), REGION_1);
+ lookup.put(REGION_2.id(), REGION_2);
+ lookup.put(REGION_3.id(), REGION_3);
+ }
+
+ @Override
+ public Set<Region> getRegions() {
+ return REGION_SET;
+ }
+
+ @Override
+ public Region getRegion(RegionId regionId) {
+ return lookup.get(regionId);
+ }
+
+ @Override
+ public Region getRegionForDevice(DeviceId deviceId) {
+ if (DEVS_TRUNK.contains(deviceId)) {
+ return REGION_1;
+ }
+ if (DEVS_LEFT.contains(deviceId)) {
+ return REGION_2;
+ }
+ if (DEVS_RIGHT.contains(deviceId)) {
+ return REGION_3;
+ }
+ return null;
+ }
+
+ @Override
+ public Set<DeviceId> getRegionDevices(RegionId regionId) {
+ if (REGION_1.id().equals(regionId)) {
+ return DEVS_TRUNK;
+ }
+ if (REGION_2.id().equals(regionId)) {
+ return DEVS_LEFT;
+ }
+ if (REGION_3.id().equals(regionId)) {
+ return DEVS_RIGHT;
+ }
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<HostId> getRegionHosts(RegionId regionId) {
+ Set<HostId> hosts = new HashSet<HostId>();
+ for (HostId hostId : HOSTS.keySet()) {
+ if (HOSTS.get(hostId).equals(regionId)) {
+ hosts.add(hostId);
+ }
+ }
+ return hosts;
+ }
+
+ @Override
+ public void addListener(RegionListener listener) {
+
+ }
+
+ @Override
+ public void removeListener(RegionListener listener) {
+
+ }
+ }
+}
\ No newline at end of file