HIGUCHI Yuta
Committed by Gerrit Code Review

[Falcon] ONOS-3372 Link related Service on gRPC

Change-Id: Ib497d17cb3c0126086a1ce03a6f99ae344320448
...@@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
23 23
24 import org.onosproject.incubator.rpc.RemoteServiceContext; 24 import org.onosproject.incubator.rpc.RemoteServiceContext;
25 import org.onosproject.net.device.DeviceProviderRegistry; 25 import org.onosproject.net.device.DeviceProviderRegistry;
26 +import org.onosproject.net.link.LinkProviderRegistry;
26 import org.slf4j.Logger; 27 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory; 28 import org.slf4j.LoggerFactory;
28 29
...@@ -49,6 +50,7 @@ public class GrpcRemoteServiceContext implements RemoteServiceContext { ...@@ -49,6 +50,7 @@ public class GrpcRemoteServiceContext implements RemoteServiceContext {
49 public GrpcRemoteServiceContext(ManagedChannel channel) { 50 public GrpcRemoteServiceContext(ManagedChannel channel) {
50 this.channel = checkNotNull(channel); 51 this.channel = checkNotNull(channel);
51 services.put(DeviceProviderRegistry.class, new DeviceProviderRegistryClientProxy(channel)); 52 services.put(DeviceProviderRegistry.class, new DeviceProviderRegistryClientProxy(channel));
53 + services.put(LinkProviderRegistry.class, new LinkProviderRegistryClientProxy(channel));
52 } 54 }
53 55
54 56
......
...@@ -21,6 +21,7 @@ import static org.onosproject.incubator.rpc.grpc.GrpcDeviceUtils.translate; ...@@ -21,6 +21,7 @@ import static org.onosproject.incubator.rpc.grpc.GrpcDeviceUtils.translate;
21 import static org.onosproject.net.DeviceId.deviceId; 21 import static org.onosproject.net.DeviceId.deviceId;
22 22
23 import java.io.IOException; 23 import java.io.IOException;
24 +import java.util.Map;
24 import java.util.Set; 25 import java.util.Set;
25 import java.util.concurrent.CompletableFuture; 26 import java.util.concurrent.CompletableFuture;
26 import java.util.concurrent.ExecutionException; 27 import java.util.concurrent.ExecutionException;
...@@ -47,11 +48,15 @@ import org.onosproject.grpc.Device.UpdatePortStatistics; ...@@ -47,11 +48,15 @@ import org.onosproject.grpc.Device.UpdatePortStatistics;
47 import org.onosproject.grpc.Device.UpdatePorts; 48 import org.onosproject.grpc.Device.UpdatePorts;
48 import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc; 49 import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc;
49 import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc.DeviceProviderRegistryRpc; 50 import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc.DeviceProviderRegistryRpc;
51 +import org.onosproject.grpc.LinkProviderServiceRpcGrpc;
50 import org.onosproject.net.DeviceId; 52 import org.onosproject.net.DeviceId;
51 import org.onosproject.net.MastershipRole; 53 import org.onosproject.net.MastershipRole;
52 import org.onosproject.net.device.DeviceProvider; 54 import org.onosproject.net.device.DeviceProvider;
53 import org.onosproject.net.device.DeviceProviderRegistry; 55 import org.onosproject.net.device.DeviceProviderRegistry;
54 import org.onosproject.net.device.DeviceProviderService; 56 import org.onosproject.net.device.DeviceProviderService;
57 +import org.onosproject.net.link.LinkProvider;
58 +import org.onosproject.net.link.LinkProviderRegistry;
59 +import org.onosproject.net.link.LinkProviderService;
55 import org.onosproject.net.provider.ProviderId; 60 import org.onosproject.net.provider.ProviderId;
56 import org.osgi.service.component.ComponentContext; 61 import org.osgi.service.component.ComponentContext;
57 import org.slf4j.Logger; 62 import org.slf4j.Logger;
...@@ -59,6 +64,7 @@ import org.slf4j.LoggerFactory; ...@@ -59,6 +64,7 @@ import org.slf4j.LoggerFactory;
59 64
60 import com.google.common.cache.Cache; 65 import com.google.common.cache.Cache;
61 import com.google.common.cache.CacheBuilder; 66 import com.google.common.cache.CacheBuilder;
67 +import com.google.common.collect.Maps;
62 import com.google.common.collect.Sets; 68 import com.google.common.collect.Sets;
63 69
64 import io.grpc.Server; 70 import io.grpc.Server;
...@@ -68,13 +74,15 @@ import io.grpc.stub.StreamObserver; ...@@ -68,13 +74,15 @@ import io.grpc.stub.StreamObserver;
68 // gRPC Server on Metro-side 74 // gRPC Server on Metro-side
69 // Translates request received on RPC channel, and calls corresponding Service on 75 // Translates request received on RPC channel, and calls corresponding Service on
70 // Metro-ONOS cluster. 76 // Metro-ONOS cluster.
77 +
78 +// Currently supports DeviceProviderRegistry, LinkProviderService
71 /** 79 /**
72 * Server side implementation of gRPC based RemoteService. 80 * Server side implementation of gRPC based RemoteService.
73 */ 81 */
74 @Component(immediate = true) 82 @Component(immediate = true)
75 public class GrpcRemoteServiceServer { 83 public class GrpcRemoteServiceServer {
76 84
77 - private static final String RPC_PROVIDER_NAME = "org.onosproject.rpc.provider.grpc"; 85 + static final String RPC_PROVIDER_NAME = "org.onosproject.rpc.provider.grpc";
78 86
79 // TODO pick a number 87 // TODO pick a number
80 public static final int DEFAULT_LISTEN_PORT = 11984; 88 public static final int DEFAULT_LISTEN_PORT = 11984;
...@@ -84,6 +92,9 @@ public class GrpcRemoteServiceServer { ...@@ -84,6 +92,9 @@ public class GrpcRemoteServiceServer {
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
85 protected DeviceProviderRegistry deviceProviderRegistry; 93 protected DeviceProviderRegistry deviceProviderRegistry;
86 94
95 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 + protected LinkProviderRegistry linkProviderRegistry;
97 +
87 98
88 @Property(name = "listenPort", intValue = DEFAULT_LISTEN_PORT, 99 @Property(name = "listenPort", intValue = DEFAULT_LISTEN_PORT,
89 label = "Port to listen on") 100 label = "Port to listen on")
...@@ -92,6 +103,11 @@ public class GrpcRemoteServiceServer { ...@@ -92,6 +103,11 @@ public class GrpcRemoteServiceServer {
92 private Server server; 103 private Server server;
93 private final Set<DeviceProviderServerProxy> registeredProviders = Sets.newConcurrentHashSet(); 104 private final Set<DeviceProviderServerProxy> registeredProviders = Sets.newConcurrentHashSet();
94 105
106 + // scheme -> ...
107 + // updates must be guarded by synchronizing `this`
108 + private final Map<String, LinkProviderService> linkProviderServices = Maps.newConcurrentMap();
109 + private final Map<String, LinkProvider> linkProviders = Maps.newConcurrentMap();
110 +
95 @Activate 111 @Activate
96 protected void activate(ComponentContext context) throws IOException { 112 protected void activate(ComponentContext context) throws IOException {
97 modified(context); 113 modified(context);
...@@ -100,6 +116,7 @@ public class GrpcRemoteServiceServer { ...@@ -100,6 +116,7 @@ public class GrpcRemoteServiceServer {
100 try { 116 try {
101 server = NettyServerBuilder.forPort(listenPort) 117 server = NettyServerBuilder.forPort(listenPort)
102 .addService(DeviceProviderRegistryRpcGrpc.bindService(new DeviceProviderRegistryServerProxy())) 118 .addService(DeviceProviderRegistryRpcGrpc.bindService(new DeviceProviderRegistryServerProxy()))
119 + .addService(LinkProviderServiceRpcGrpc.bindService(new LinkProviderServiceServerProxy(this)))
103 .build().start(); 120 .build().start();
104 } catch (IOException e) { 121 } catch (IOException e) {
105 log.error("Failed to start gRPC server", e); 122 log.error("Failed to start gRPC server", e);
...@@ -117,6 +134,9 @@ public class GrpcRemoteServiceServer { ...@@ -117,6 +134,9 @@ public class GrpcRemoteServiceServer {
117 134
118 server.shutdown(); 135 server.shutdown();
119 // Should we wait for shutdown? 136 // Should we wait for shutdown?
137 +
138 + unregisterLinkProviders();
139 +
120 log.info("Stopped"); 140 log.info("Stopped");
121 } 141 }
122 142
...@@ -125,6 +145,40 @@ public class GrpcRemoteServiceServer { ...@@ -125,6 +145,40 @@ public class GrpcRemoteServiceServer {
125 // TODO support dynamic reconfiguration and restarting server? 145 // TODO support dynamic reconfiguration and restarting server?
126 } 146 }
127 147
148 + /**
149 + * Registers {@link StubLinkProvider} for given ProviderId scheme.
150 + *
151 + * DO NOT DIRECTLY CALL THIS METHOD.
152 + * Only expected to be called from {@link #getLinkProviderServiceFor(String)}.
153 + *
154 + * @param scheme ProviderId scheme.
155 + * @return {@link LinkProviderService} registered.
156 + */
157 + private synchronized LinkProviderService registerStubLinkProvider(String scheme) {
158 + StubLinkProvider provider = new StubLinkProvider(scheme);
159 + linkProviders.put(scheme, provider);
160 + return linkProviderRegistry.register(provider);
161 + }
162 +
163 + /**
164 + * Unregisters all registered LinkProviders.
165 + */
166 + private synchronized void unregisterLinkProviders() {
167 + linkProviders.values().forEach(linkProviderRegistry::unregister);
168 + linkProviders.clear();
169 + linkProviderServices.clear();
170 + }
171 +
172 + /**
173 + * Gets or creates {@link LinkProviderService} registered for given ProviderId scheme.
174 + *
175 + * @param scheme ProviderId scheme.
176 + * @return {@link LinkProviderService}
177 + */
178 + protected LinkProviderService getLinkProviderServiceFor(String scheme) {
179 + return linkProviderServices.computeIfAbsent(scheme, this::registerStubLinkProvider);
180 + }
181 +
128 // RPC Server-side code 182 // RPC Server-side code
129 // RPC session Factory 183 // RPC session Factory
130 /** 184 /**
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.incubator.rpc.grpc;
17 +
18 +import static com.google.common.base.Preconditions.checkNotNull;
19 +
20 +import org.onosproject.net.link.LinkProvider;
21 +import org.onosproject.net.link.LinkProviderRegistry;
22 +import org.onosproject.net.link.LinkProviderService;
23 +import org.onosproject.net.provider.AbstractProviderRegistry;
24 +
25 +import com.google.api.client.repackaged.com.google.common.annotations.Beta;
26 +
27 +import io.grpc.Channel;
28 +
29 +/**
30 + * Proxy object to handle LinkProviderRegistry calls.
31 + */
32 +@Beta
33 +public class LinkProviderRegistryClientProxy
34 + extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
35 + implements LinkProviderRegistry {
36 +
37 + private final Channel channel;
38 +
39 + public LinkProviderRegistryClientProxy(Channel channel) {
40 + this.channel = checkNotNull(channel);
41 + }
42 +
43 + @Override
44 + protected LinkProviderService createProviderService(LinkProvider provider) {
45 + return new LinkProviderServiceClientProxy(provider, channel);
46 + }
47 +
48 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.incubator.rpc.grpc;
17 +
18 +import static org.onosproject.incubator.rpc.grpc.GrpcDeviceUtils.asMap;
19 +
20 +import java.util.concurrent.ExecutionException;
21 +import java.util.concurrent.TimeUnit;
22 +import java.util.concurrent.TimeoutException;
23 +
24 +import org.onosproject.grpc.Link.LinkDetectedMsg;
25 +import org.onosproject.grpc.Link.LinkType;
26 +import org.onosproject.grpc.Link.LinkVanishedMsg;
27 +import org.onosproject.grpc.Link.Void;
28 +import org.onosproject.grpc.LinkProviderServiceRpcGrpc;
29 +import org.onosproject.grpc.LinkProviderServiceRpcGrpc.LinkProviderServiceRpcFutureStub;
30 +import org.onosproject.net.ConnectPoint;
31 +import org.onosproject.net.DeviceId;
32 +import org.onosproject.net.Link.Type;
33 +import org.onosproject.net.link.LinkDescription;
34 +import org.onosproject.net.link.LinkProvider;
35 +import org.onosproject.net.link.LinkProviderService;
36 +import org.onosproject.net.provider.AbstractProviderService;
37 +import org.onosproject.net.provider.ProviderId;
38 +import org.slf4j.Logger;
39 +import org.slf4j.LoggerFactory;
40 +
41 +import com.google.api.client.repackaged.com.google.common.annotations.Beta;
42 +import com.google.common.util.concurrent.ListenableFuture;
43 +
44 +import io.grpc.Channel;
45 +
46 +/**
47 + * Proxy object to handle LinkProviderService calls.
48 + *
49 + * RPC wise, this will initiate a RPC call on each method invocation.
50 + */
51 +@Beta
52 +class LinkProviderServiceClientProxy
53 + extends AbstractProviderService<LinkProvider>
54 + implements LinkProviderService {
55 +
56 + private final Logger log = LoggerFactory.getLogger(getClass());
57 +
58 + private final Channel channel;
59 +
60 + /**
61 + * Constructs {@link LinkProviderServiceClientProxy}.
62 + *
63 + * @param provider {@link LinkProvider}. Only ProviderId scheme is used.
64 + * @param channel channel to use to call RPC
65 + */
66 + protected LinkProviderServiceClientProxy(LinkProvider provider, Channel channel) {
67 + super(provider);
68 + this.channel = channel;
69 + }
70 +
71 + @Override
72 + public void linkDetected(LinkDescription linkDescription) {
73 + checkValidity();
74 +
75 + LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
76 + ListenableFuture<Void> future = newStub.linkDetected(detectMsg(provider().id(), linkDescription));
77 +
78 + try {
79 + // There's no need to wait, but just checking server
80 + future.get(500, TimeUnit.MILLISECONDS);
81 + } catch (InterruptedException e) {
82 + log.error("linkDetected({}) failed", linkDescription, e);
83 + invalidate();
84 + Thread.currentThread().interrupt();
85 + } catch (ExecutionException e) {
86 + log.error("linkDetected({}) failed", linkDescription, e);
87 + invalidate();
88 + } catch (TimeoutException e) {
89 + log.error("linkDetected({}) failed", linkDescription, e);
90 + invalidate();
91 + }
92 + }
93 +
94 + @Override
95 + public void linkVanished(LinkDescription linkDescription) {
96 + checkValidity();
97 +
98 + LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
99 + ListenableFuture<Void> future = newStub.linkVanished(vanishMsg(provider().id(), linkDescription));
100 +
101 + try {
102 + // There's no need to wait, but just checking server
103 + future.get(500, TimeUnit.MILLISECONDS);
104 + } catch (InterruptedException e) {
105 + log.error("linkVanished({}) failed", linkDescription, e);
106 + invalidate();
107 + Thread.currentThread().interrupt();
108 + } catch (ExecutionException e) {
109 + log.error("linkVanished({}) failed", linkDescription, e);
110 + invalidate();
111 + } catch (TimeoutException e) {
112 + log.error("linkVanished({}) failed", linkDescription, e);
113 + invalidate();
114 + }
115 + }
116 +
117 + @Override
118 + public void linksVanished(ConnectPoint connectPoint) {
119 + checkValidity();
120 +
121 + LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
122 + ListenableFuture<Void> future = newStub.linkVanished(vanishMsg(provider().id(), connectPoint));
123 +
124 + try {
125 + // There's no need to wait, but just checking server
126 + future.get(500, TimeUnit.MILLISECONDS);
127 + } catch (InterruptedException e) {
128 + log.error("linksVanished({}) failed", connectPoint, e);
129 + invalidate();
130 + Thread.currentThread().interrupt();
131 + } catch (ExecutionException e) {
132 + log.error("linksVanished({}) failed", connectPoint, e);
133 + invalidate();
134 + } catch (TimeoutException e) {
135 + log.error("linksVanished({}) failed", connectPoint, e);
136 + invalidate();
137 + }
138 + }
139 +
140 + @Override
141 + public void linksVanished(DeviceId deviceId) {
142 + checkValidity();
143 +
144 + LinkProviderServiceRpcFutureStub newStub = LinkProviderServiceRpcGrpc.newFutureStub(channel);
145 + ListenableFuture<Void> future = newStub.linkVanished(vanishMsg(provider().id(), deviceId));
146 +
147 + try {
148 + // There's no need to wait, but just checking server
149 + future.get(500, TimeUnit.MILLISECONDS);
150 + } catch (InterruptedException e) {
151 + log.error("linksVanished({}) failed", deviceId, e);
152 + invalidate();
153 + Thread.currentThread().interrupt();
154 + } catch (ExecutionException e) {
155 + log.error("linksVanished({}) failed", deviceId, e);
156 + invalidate();
157 + } catch (TimeoutException e) {
158 + log.error("linksVanished({}) failed", deviceId, e);
159 + invalidate();
160 + }
161 + }
162 +
163 + /**
164 + * Builds {@link LinkDetectedMsg}.
165 + *
166 + * @param id ProviderId
167 + * @param linkDescription {@link LinkDescription}
168 + * @return {@link LinkDetectedMsg}
169 + */
170 + private LinkDetectedMsg detectMsg(ProviderId id,
171 + LinkDescription linkDescription) {
172 + LinkDetectedMsg.Builder builder = LinkDetectedMsg.newBuilder();
173 + builder.setProviderId(id.scheme())
174 + .setLinkDescription(builder.getLinkDescriptionBuilder()
175 + .setSrc(translate(linkDescription.src()))
176 + .setDst(translate(linkDescription.dst()))
177 + .setType(translate(linkDescription.type()))
178 + .putAllAnnotations(asMap(linkDescription.annotations()))
179 + .build()
180 + );
181 + return builder.build();
182 + }
183 +
184 + /**
185 + * Builds {@link LinkVanishedMsg}.
186 + *
187 + * @param id ProviderId
188 + * @param linkDescription {@link LinkDescription}
189 + * @return {@link LinkVanishedMsg}
190 + */
191 + private LinkVanishedMsg vanishMsg(ProviderId id,
192 + LinkDescription linkDescription) {
193 +
194 + LinkVanishedMsg.Builder builder = LinkVanishedMsg.newBuilder();
195 + builder.setProviderId(id.scheme())
196 + .setLinkDescription(builder.getLinkDescriptionBuilder()
197 + .setSrc(translate(linkDescription.src()))
198 + .setDst(translate(linkDescription.dst()))
199 + .setType(translate(linkDescription.type()))
200 + .putAllAnnotations(asMap(linkDescription.annotations()))
201 + .build()
202 + );
203 + return builder.build();
204 + }
205 +
206 + /**
207 + * Builds {@link LinkVanishedMsg}.
208 + *
209 + * @param id ProviderId
210 + * @param connectPoint {@link ConnectPoint}
211 + * @return {@link LinkVanishedMsg}
212 + */
213 + private LinkVanishedMsg vanishMsg(ProviderId id,
214 + ConnectPoint connectPoint) {
215 +
216 + LinkVanishedMsg.Builder builder = LinkVanishedMsg.newBuilder();
217 + builder.setProviderId(id.scheme())
218 + .setConnectPoint(translate(connectPoint));
219 + return builder.build();
220 + }
221 +
222 + /**
223 + * Builds {@link LinkVanishedMsg}.
224 + *
225 + * @param id ProviderId
226 + * @param deviceId {@link DeviceId}
227 + * @return {@link LinkVanishedMsg}
228 + */
229 + private LinkVanishedMsg vanishMsg(ProviderId id, DeviceId deviceId) {
230 +
231 + LinkVanishedMsg.Builder builder = LinkVanishedMsg.newBuilder();
232 + builder.setProviderId(id.scheme())
233 + .setDeviceId(deviceId.toString());
234 + return builder.build();
235 + }
236 +
237 + /**
238 + * Translates ONOS object to gRPC message.
239 + *
240 + * @param type {@link Link.Type}
241 + * @return gRPC LinkType
242 + */
243 + private LinkType translate(Type type) {
244 + switch (type) {
245 + case DIRECT:
246 + return LinkType.DIRECT;
247 + case EDGE:
248 + return LinkType.EDGE;
249 + case INDIRECT:
250 + return LinkType.INDIRECT;
251 + case OPTICAL:
252 + return LinkType.OPTICAL;
253 + case TUNNEL:
254 + return LinkType.TUNNEL;
255 + case VIRTUAL:
256 + return LinkType.VIRTUAL;
257 +
258 + default:
259 + return LinkType.DIRECT;
260 +
261 + }
262 + }
263 +
264 + /**
265 + * Translates ONOS object to gRPC message.
266 + *
267 + * @param cp {@link ConnectPoint}
268 + * @return gRPC ConnectPoint
269 + */
270 + private org.onosproject.grpc.Link.ConnectPoint translate(ConnectPoint cp) {
271 + return org.onosproject.grpc.Link.ConnectPoint.newBuilder()
272 + .setDeviceId(cp.deviceId().toString())
273 + .setPortNumber(cp.port().toString())
274 + .build();
275 + }
276 +
277 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.incubator.rpc.grpc;
17 +
18 +import static com.google.common.base.Preconditions.checkArgument;
19 +import static com.google.common.base.Preconditions.checkNotNull;
20 +import static org.onosproject.net.DeviceId.deviceId;
21 +
22 +import org.onosproject.grpc.Link.LinkDetectedMsg;
23 +import org.onosproject.grpc.Link.LinkType;
24 +import org.onosproject.grpc.Link.LinkVanishedMsg;
25 +import org.onosproject.grpc.Link.Void;
26 +import org.onosproject.grpc.Link.ConnectPoint.ElementIdCase;
27 +import org.onosproject.grpc.LinkProviderServiceRpcGrpc.LinkProviderServiceRpc;
28 +import org.onosproject.net.ConnectPoint;
29 +import org.onosproject.net.DeviceId;
30 +import org.onosproject.net.Link;
31 +import org.onosproject.net.PortNumber;
32 +import org.onosproject.net.SparseAnnotations;
33 +import org.onosproject.net.link.DefaultLinkDescription;
34 +import org.onosproject.net.link.LinkDescription;
35 +import org.onosproject.net.link.LinkProviderService;
36 +import org.slf4j.Logger;
37 +import org.slf4j.LoggerFactory;
38 +
39 +import com.google.api.client.repackaged.com.google.common.annotations.Beta;
40 +
41 +import io.grpc.stub.StreamObserver;
42 +
43 +/**
44 + * Server-side implementation of gRPC version of LinkProviderService.
45 + */
46 +@Beta
47 +final class LinkProviderServiceServerProxy
48 + implements LinkProviderServiceRpc {
49 +
50 + private final Logger log = LoggerFactory.getLogger(getClass());
51 +
52 + private final GrpcRemoteServiceServer server;
53 +
54 + LinkProviderServiceServerProxy(GrpcRemoteServiceServer server) {
55 + this.server = checkNotNull(server);
56 + }
57 +
58 + /**
59 + * Gets or creates {@link LinkProviderService} registered for given ProviderId scheme.
60 + *
61 + * @param scheme ProviderId scheme.
62 + * @return {@link LinkProviderService}
63 + */
64 + private LinkProviderService getLinkProviderServiceFor(String scheme) {
65 + return server.getLinkProviderServiceFor(scheme);
66 + }
67 +
68 + @Override
69 + public void linkDetected(LinkDetectedMsg request,
70 + StreamObserver<Void> responseObserver) {
71 +
72 + try {
73 + onLinkDetected(request, responseObserver);
74 + // If onNext call was not mandatory, it can be removed.
75 + responseObserver.onNext(Void.getDefaultInstance());
76 + responseObserver.onCompleted();
77 + } catch (Exception e) {
78 + log.error("Exception caught", e);
79 + responseObserver.onError(e);
80 + }
81 + }
82 +
83 + private void onLinkDetected(LinkDetectedMsg request,
84 + StreamObserver<Void> responseObserver) {
85 + String scheme = request.getProviderId();
86 +
87 + LinkProviderService linkProviderService = getLinkProviderServiceFor(scheme);
88 +
89 + LinkDescription linkDescription = translate(request.getLinkDescription());
90 + linkProviderService.linkDetected(linkDescription);
91 + }
92 +
93 + @Override
94 + public void linkVanished(LinkVanishedMsg request,
95 + StreamObserver<Void> responseObserver) {
96 + try {
97 + onLinksVanished(request, responseObserver);
98 + // If onNext call was not mandatory, it can be removed.
99 + responseObserver.onNext(Void.getDefaultInstance());
100 + responseObserver.onCompleted();
101 + } catch (Exception e) {
102 + log.error("Exception caught", e);
103 + responseObserver.onError(e);
104 + }
105 + }
106 +
107 + private void onLinksVanished(LinkVanishedMsg request,
108 + StreamObserver<Void> responseObserver) {
109 + String scheme = request.getProviderId();
110 + switch (request.getSubjectCase()) {
111 + case CONNECT_POINT:
112 + ConnectPoint cp = translate(request.getConnectPoint());
113 + getLinkProviderServiceFor(scheme).linksVanished(cp);
114 + break;
115 + case DEVICE_ID:
116 + DeviceId did = deviceId(request.getDeviceId());
117 + getLinkProviderServiceFor(scheme).linksVanished(did);
118 + break;
119 + case LINK_DESCRIPTION:
120 + LinkDescription desc = translate(request.getLinkDescription());
121 + getLinkProviderServiceFor(scheme).linkVanished(desc);
122 + break;
123 + case SUBJECT_NOT_SET:
124 + default:
125 + // do nothing
126 + break;
127 + }
128 + }
129 +
130 + /**
131 + * Translates gRPC message to corresponding ONOS object.
132 + *
133 + * @param connectPoint gRPC message.
134 + * @return {@link ConnectPoint}
135 + */
136 + private ConnectPoint translate(org.onosproject.grpc.Link.ConnectPoint connectPoint) {
137 + checkArgument(connectPoint.getElementIdCase() == ElementIdCase.DEVICE_ID,
138 + "Only DeviceId supported.");
139 + return new ConnectPoint(deviceId(connectPoint.getDeviceId()),
140 + PortNumber.fromString(connectPoint.getPortNumber()));
141 + }
142 +
143 + /**
144 + * Translates gRPC message to corresponding ONOS object.
145 + *
146 + * @param linkDescription gRPC message
147 + * @return {@link LinkDescription}
148 + */
149 + private LinkDescription translate(org.onosproject.grpc.Link.LinkDescription linkDescription) {
150 + ConnectPoint src = translate(linkDescription.getSrc());
151 + ConnectPoint dst = translate(linkDescription.getDst());
152 + Link.Type type = translate(linkDescription.getType());
153 + SparseAnnotations annotations = GrpcDeviceUtils.asAnnotations(linkDescription.getAnnotations());
154 + return new DefaultLinkDescription(src, dst, type, annotations);
155 + }
156 +
157 + /**
158 + * Translates gRPC message to corresponding ONOS object.
159 + *
160 + * @param type gRPC message enum
161 + * @return {@link Type}
162 + */
163 + private Link.Type translate(LinkType type) {
164 + switch (type) {
165 + case DIRECT:
166 + return Link.Type.DIRECT;
167 + case EDGE:
168 + return Link.Type.EDGE;
169 + case INDIRECT:
170 + return Link.Type.INDIRECT;
171 + case OPTICAL:
172 + return Link.Type.INDIRECT;
173 + case TUNNEL:
174 + return Link.Type.TUNNEL;
175 + case VIRTUAL:
176 + return Link.Type.VIRTUAL;
177 +
178 + case UNRECOGNIZED:
179 + default:
180 + return Link.Type.DIRECT;
181 + }
182 + }
183 +
184 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.incubator.rpc.grpc;
17 +
18 +import org.onosproject.net.link.LinkProvider;
19 +import org.onosproject.net.provider.AbstractProvider;
20 +import org.onosproject.net.provider.ProviderId;
21 +
22 +import com.google.api.client.repackaged.com.google.common.annotations.Beta;
23 +import com.google.common.base.MoreObjects;
24 +
25 +/**
26 + * Stub LinkProvider to be registered on Server-side.
27 + */
28 +@Beta
29 +final class StubLinkProvider extends AbstractProvider implements LinkProvider {
30 + protected StubLinkProvider(String scheme) {
31 + super(new ProviderId(scheme, GrpcRemoteServiceServer.RPC_PROVIDER_NAME));
32 + }
33 +
34 + @Override
35 + public String toString() {
36 + return MoreObjects.toStringHelper(this)
37 + .add("id", id())
38 + .toString();
39 + }
40 +}
1 +syntax = "proto3";
2 +option java_package = "org.onosproject.grpc";
3 +
4 +package Link;
5 +
6 +enum LinkType {
7 + // Signifies that this is a direct single-segment link.
8 + DIRECT = 0;
9 +
10 + // Signifies that this link is potentially comprised from multiple
11 + //underlying segments or hops, and as such should be used to tag
12 + // links traversing optical paths, tunnels or intervening 'dark'
13 + // switches.
14 + INDIRECT = 1;
15 +
16 + // Signifies that this link is an edge, i.e. host link.
17 + EDGE = 2;
18 +
19 + // Signifies that this link represents a logical link backed by
20 + // some form of a tunnel, e.g., GRE, MPLS, ODUk, OCH.
21 + TUNNEL = 3;
22 +
23 + // Signifies that this link is realized by fiber (either single channel or WDM).
24 + OPTICAL = 4;
25 +
26 + // Signifies that this link is a virtual link or a pseudo-wire.
27 + VIRTUAL = 5;
28 +}
29 +
30 +message ConnectPoint {
31 + oneof element_id {
32 + // DeviceID as String DeviceId#toString
33 + string device_id = 1;
34 +
35 + // TODO add support to other element_id if required
36 + }
37 + // PortNumber as String PortNumber#toString
38 + string port_number = 2;
39 +}
40 +
41 +message LinkDescription {
42 + ConnectPoint src = 1;
43 + ConnectPoint dst = 2;
44 + LinkType type = 3;
45 + map<string, string> annotations = 4;
46 +}
47 +
48 +// Message te represent no return value
49 +message Void {}
50 +
51 +message LinkDetectedMsg {
52 + // ProviderId scheme only
53 + string provider_id = 1;
54 + LinkDescription link_description = 2;
55 +}
56 +
57 +message LinkVanishedMsg {
58 + // ProviderId scheme only
59 + string provider_id = 1;
60 + oneof subject {
61 + LinkDescription link_description = 2;
62 + ConnectPoint connect_point = 3;
63 + string device_id = 4;
64 + }
65 +}
66 +
67 +service LinkProviderServiceRpc {
68 + rpc LinkDetected(LinkDetectedMsg) returns (Void);
69 + rpc LinkVanished(LinkVanishedMsg) returns (Void);
70 +}
...@@ -17,6 +17,7 @@ package org.onosproject.incubator.rpc.grpc; ...@@ -17,6 +17,7 @@ package org.onosproject.incubator.rpc.grpc;
17 17
18 import static org.junit.Assert.*; 18 import static org.junit.Assert.*;
19 import static org.onosproject.net.DeviceId.deviceId; 19 import static org.onosproject.net.DeviceId.deviceId;
20 +import static org.onosproject.net.PortNumber.portNumber;
20 21
21 import java.io.IOException; 22 import java.io.IOException;
22 import java.net.ServerSocket; 23 import java.net.ServerSocket;
...@@ -37,9 +38,11 @@ import org.onosproject.incubator.rpc.RemoteServiceContext; ...@@ -37,9 +38,11 @@ import org.onosproject.incubator.rpc.RemoteServiceContext;
37 import org.onosproject.incubator.rpc.RemoteServiceContextProvider; 38 import org.onosproject.incubator.rpc.RemoteServiceContextProvider;
38 import org.onosproject.incubator.rpc.RemoteServiceContextProviderService; 39 import org.onosproject.incubator.rpc.RemoteServiceContextProviderService;
39 import org.onosproject.incubator.rpc.RemoteServiceProviderRegistry; 40 import org.onosproject.incubator.rpc.RemoteServiceProviderRegistry;
41 +import org.onosproject.net.ConnectPoint;
40 import org.onosproject.net.DefaultAnnotations; 42 import org.onosproject.net.DefaultAnnotations;
41 import org.onosproject.net.Device.Type; 43 import org.onosproject.net.Device.Type;
42 import org.onosproject.net.DeviceId; 44 import org.onosproject.net.DeviceId;
45 +import org.onosproject.net.Link;
43 import org.onosproject.net.MastershipRole; 46 import org.onosproject.net.MastershipRole;
44 import org.onosproject.net.PortNumber; 47 import org.onosproject.net.PortNumber;
45 import org.onosproject.net.SparseAnnotations; 48 import org.onosproject.net.SparseAnnotations;
...@@ -51,6 +54,11 @@ import org.onosproject.net.device.DeviceProviderRegistry; ...@@ -51,6 +54,11 @@ import org.onosproject.net.device.DeviceProviderRegistry;
51 import org.onosproject.net.device.DeviceProviderService; 54 import org.onosproject.net.device.DeviceProviderService;
52 import org.onosproject.net.device.PortDescription; 55 import org.onosproject.net.device.PortDescription;
53 import org.onosproject.net.device.PortStatistics; 56 import org.onosproject.net.device.PortStatistics;
57 +import org.onosproject.net.link.DefaultLinkDescription;
58 +import org.onosproject.net.link.LinkDescription;
59 +import org.onosproject.net.link.LinkProvider;
60 +import org.onosproject.net.link.LinkProviderRegistry;
61 +import org.onosproject.net.link.LinkProviderService;
54 import org.onosproject.net.provider.AbstractProviderRegistry; 62 import org.onosproject.net.provider.AbstractProviderRegistry;
55 import org.onosproject.net.provider.AbstractProviderService; 63 import org.onosproject.net.provider.AbstractProviderService;
56 import org.onosproject.net.provider.ProviderId; 64 import org.onosproject.net.provider.ProviderId;
...@@ -99,6 +107,9 @@ public class GrpcRemoteServiceTest { ...@@ -99,6 +107,9 @@ public class GrpcRemoteServiceTest {
99 107
100 private MTestDeviceProviderService svDeviceProviderService; 108 private MTestDeviceProviderService svDeviceProviderService;
101 109
110 + private ServerSideLinkProviderService svLinkProviderService;
111 +
112 +
102 private CountDownLatch serverReady; 113 private CountDownLatch serverReady;
103 114
104 private URI uri; 115 private URI uri;
...@@ -121,6 +132,7 @@ public class GrpcRemoteServiceTest { ...@@ -121,6 +132,7 @@ public class GrpcRemoteServiceTest {
121 serverReady = new CountDownLatch(1); 132 serverReady = new CountDownLatch(1);
122 server = new GrpcRemoteServiceServer(); 133 server = new GrpcRemoteServiceServer();
123 server.deviceProviderRegistry = new MTestDeviceProviderRegistry(); 134 server.deviceProviderRegistry = new MTestDeviceProviderRegistry();
135 + server.linkProviderRegistry = new ServerSideLinkProviderRegistry();
124 // todo: pass proper ComponentContext 136 // todo: pass proper ComponentContext
125 server.listenPort = pickListenPort(); 137 server.listenPort = pickListenPort();
126 uri = URI.create("grpc://localhost:" + server.listenPort); 138 uri = URI.create("grpc://localhost:" + server.listenPort);
...@@ -135,6 +147,7 @@ public class GrpcRemoteServiceTest { ...@@ -135,6 +147,7 @@ public class GrpcRemoteServiceTest {
135 public void tearDown() { 147 public void tearDown() {
136 client.deactivate(); 148 client.deactivate();
137 server.deactivate(); 149 server.deactivate();
150 + svLinkProviderService = null;
138 } 151 }
139 152
140 private static void assertEqualsButNotSame(Object expected, Object actual) { 153 private static void assertEqualsButNotSame(Object expected, Object actual) {
...@@ -144,7 +157,7 @@ public class GrpcRemoteServiceTest { ...@@ -144,7 +157,7 @@ public class GrpcRemoteServiceTest {
144 } 157 }
145 158
146 @Test 159 @Test
147 - public void basics() throws InterruptedException { 160 + public void deviceServiceBasics() throws InterruptedException {
148 RemoteServiceContext remoteServiceContext = client.get(uri); 161 RemoteServiceContext remoteServiceContext = client.get(uri);
149 assertNotNull(remoteServiceContext); 162 assertNotNull(remoteServiceContext);
150 163
...@@ -217,6 +230,116 @@ public class GrpcRemoteServiceTest { ...@@ -217,6 +230,116 @@ public class GrpcRemoteServiceTest {
217 DEVICE_ID, clDeviceProvider.isReachableDid); 230 DEVICE_ID, clDeviceProvider.isReachableDid);
218 } 231 }
219 232
233 + @Test
234 + public void linkVanishedDevice() throws InterruptedException {
235 + RemoteServiceContext remoteServiceContext = client.get(uri);
236 + assertNotNull(remoteServiceContext);
237 +
238 + LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
239 + assertNotNull(providerRegistry);
240 +
241 + final String schemeTest = "test";
242 + LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
243 + assertNotNull(client);
244 +
245 + client.linksVanished(DEVICE_ID);
246 +
247 + assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
248 + assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
249 + assertEqualsButNotSame(DEVICE_ID, svLinkProviderService.arg);
250 + }
251 +
252 + @Test
253 + public void linkVanishedPort() throws InterruptedException {
254 + RemoteServiceContext remoteServiceContext = client.get(uri);
255 + assertNotNull(remoteServiceContext);
256 +
257 + LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
258 + assertNotNull(providerRegistry);
259 +
260 + final String schemeTest = "test";
261 + LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
262 + assertNotNull(client);
263 +
264 +
265 + final ConnectPoint cp = new ConnectPoint(DEVICE_ID, PORT);
266 + client.linksVanished(cp);
267 + assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
268 + assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
269 + assertEqualsButNotSame(cp, svLinkProviderService.arg);
270 + }
271 +
272 + @Test
273 + public void linkVanishedDescription() throws InterruptedException {
274 + RemoteServiceContext remoteServiceContext = client.get(uri);
275 + assertNotNull(remoteServiceContext);
276 +
277 + LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
278 + assertNotNull(providerRegistry);
279 +
280 + final String schemeTest = "test";
281 + LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
282 + assertNotNull(client);
283 +
284 + ConnectPoint src = new ConnectPoint(deviceId("dev:1"), portNumber(10));
285 + ConnectPoint dst = new ConnectPoint(deviceId("dev:2"), portNumber(20));
286 + LinkDescription linkDescription = new DefaultLinkDescription(src, dst, Link.Type.DIRECT, ANON);
287 + client.linkVanished(linkDescription);
288 + assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
289 + assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
290 + assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);
291 + }
292 +
293 + @Test
294 + public void linkDetected() throws InterruptedException {
295 + RemoteServiceContext remoteServiceContext = client.get(uri);
296 + assertNotNull(remoteServiceContext);
297 +
298 + LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
299 + assertNotNull(providerRegistry);
300 +
301 + final String schemeTest = "test";
302 + LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
303 + assertNotNull(client);
304 +
305 + ConnectPoint src = new ConnectPoint(deviceId("dev:1"), portNumber(10));
306 + ConnectPoint dst = new ConnectPoint(deviceId("dev:2"), portNumber(20));
307 + LinkDescription linkDescription = new DefaultLinkDescription(src, dst, Link.Type.DIRECT, ANON);
308 + client.linkDetected(linkDescription);
309 + assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
310 + assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
311 + assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);
312 + }
313 +
314 + @Test
315 + public void linkServiceBasics() throws InterruptedException {
316 + RemoteServiceContext remoteServiceContext = client.get(uri);
317 + assertNotNull(remoteServiceContext);
318 +
319 + LinkProviderRegistry providerRegistry = remoteServiceContext.get(LinkProviderRegistry.class);
320 + assertNotNull(providerRegistry);
321 +
322 + final String schemeTest = "test";
323 + LinkProviderService client = providerRegistry.register(new StubLinkProvider(schemeTest));
324 + assertNotNull(client);
325 +
326 + ConnectPoint src = new ConnectPoint(deviceId("dev:1"), portNumber(10));
327 + ConnectPoint dst = new ConnectPoint(deviceId("dev:2"), portNumber(20));
328 + LinkDescription linkDescription = new DefaultLinkDescription(src, dst, Link.Type.DIRECT, ANON);
329 +
330 + client.linkDetected(linkDescription);
331 + assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
332 + assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
333 + assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);
334 +
335 + svLinkProviderService.reset();
336 +
337 + client.linkVanished(linkDescription);
338 + assertEquals(schemeTest, svLinkProviderService.provider().id().scheme());
339 + assertTrue(svLinkProviderService.calls.await(10, TimeUnit.SECONDS));
340 + assertEqualsButNotSame(linkDescription, svLinkProviderService.arg);
341 + }
342 +
220 /** 343 /**
221 * Device Provider on CO side. 344 * Device Provider on CO side.
222 */ 345 */
...@@ -395,4 +518,61 @@ public class GrpcRemoteServiceTest { ...@@ -395,4 +518,61 @@ public class GrpcRemoteServiceTest {
395 } 518 }
396 } 519 }
397 520
521 + public class ServerSideLinkProviderRegistry
522 + extends AbstractProviderRegistry<LinkProvider, LinkProviderService>
523 + implements LinkProviderRegistry {
524 +
525 + @Override
526 + protected LinkProviderService createProviderService(LinkProvider provider) {
527 + svLinkProviderService = new ServerSideLinkProviderService(provider);
528 + return svLinkProviderService;
529 + }
530 +
531 + }
532 +
533 + public class ServerSideLinkProviderService
534 + extends AbstractProviderService<LinkProvider>
535 + implements LinkProviderService {
536 +
537 + CountDownLatch calls = new CountDownLatch(1);
538 + Object arg = null;
539 +
540 + public void reset() {
541 + calls = new CountDownLatch(1);
542 + arg = null;
543 + }
544 +
545 + public ServerSideLinkProviderService(LinkProvider provider) {
546 + super(provider);
547 + }
548 +
549 + @Override
550 + public void linksVanished(DeviceId deviceId) {
551 + log.info("linksVanished({})", deviceId);
552 + arg = deviceId;
553 + calls.countDown();
554 + }
555 +
556 + @Override
557 + public void linksVanished(ConnectPoint connectPoint) {
558 + log.info("linksVanished({})", connectPoint);
559 + arg = connectPoint;
560 + calls.countDown();
561 + }
562 +
563 + @Override
564 + public void linkVanished(LinkDescription linkDescription) {
565 + log.info("linksVanished({})", linkDescription);
566 + arg = linkDescription;
567 + calls.countDown();
568 + }
569 +
570 + @Override
571 + public void linkDetected(LinkDescription linkDescription) {
572 + log.info("linkDetected({})", linkDescription);
573 + arg = linkDescription;
574 + calls.countDown();
575 + }
576 + }
577 +
398 } 578 }
......