Committed by
Gerrit Code Review
ONOS-3323 gRPC implementation of Remote Service
- Start modelling Device related service (ONOS-3306) - exclude machine generated code from doc Change-Id: Idffbcd883f813de79c6f05fedc9475f308efcc31
Showing
15 changed files
with
2238 additions
and
5 deletions
... | @@ -46,11 +46,13 @@ | ... | @@ -46,11 +46,13 @@ |
46 | <plugin> | 46 | <plugin> |
47 | <groupId>org.apache.maven.plugins</groupId> | 47 | <groupId>org.apache.maven.plugins</groupId> |
48 | <artifactId>maven-javadoc-plugin</artifactId> | 48 | <artifactId>maven-javadoc-plugin</artifactId> |
49 | - <version>2.10.1</version> | 49 | + <version>2.10.3</version> |
50 | <configuration> | 50 | <configuration> |
51 | <show>package</show> | 51 | <show>package</show> |
52 | - <excludePackageNames>@external-excludes | 52 | + <excludePackageNames>@external-excludes</excludePackageNames> |
53 | - </excludePackageNames> | 53 | + <sourceFileExcludes> |
54 | + <sourceFileExclude>**/generated-sources/**</sourceFileExclude> | ||
55 | + </sourceFileExcludes> | ||
54 | <docfilessubdirs>true</docfilessubdirs> | 56 | <docfilessubdirs>true</docfilessubdirs> |
55 | <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle> | 57 | <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle> |
56 | <groups> | 58 | <groups> | ... | ... |
... | @@ -51,8 +51,11 @@ | ... | @@ -51,8 +51,11 @@ |
51 | <show>package</show> | 51 | <show>package</show> |
52 | <docfilessubdirs>true</docfilessubdirs> | 52 | <docfilessubdirs>true</docfilessubdirs> |
53 | <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle> | 53 | <doctitle>ONOS Java API (1.4.0-SNAPSHOT)</doctitle> |
54 | - <excludePackageNames>@internal-excludes | 54 | + <excludePackageNames>@internal-excludes</excludePackageNames> |
55 | - </excludePackageNames> | 55 | + <sourceFileExcludes> |
56 | + <sourceFileExclude>**/generated-sources/**</sourceFileExclude> | ||
57 | + </sourceFileExcludes> | ||
58 | + | ||
56 | <groups> | 59 | <groups> |
57 | <group> | 60 | <group> |
58 | <title>Network Model & Services</title> | 61 | <title>Network Model & Services</title> | ... | ... |
incubator/rpc-grpc/features.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}"> | ||
18 | + <feature name="${project.artifactId}" version="${project.version}" | ||
19 | + description="${project.description}"> | ||
20 | + <feature>onos-api</feature> | ||
21 | + <bundle>mvn:com.google.protobuf/protobuf-java/3.0.0-beta-1</bundle> | ||
22 | + <bundle>mvn:io.netty/netty-common/4.1.0.Beta6</bundle> | ||
23 | + <bundle>mvn:io.netty/netty-buffer/4.1.0.Beta6</bundle> | ||
24 | + <bundle>mvn:io.netty/netty-transport/4.1.0.Beta6</bundle> | ||
25 | + <bundle>mvn:io.netty/netty-handler/4.1.0.Beta6</bundle> | ||
26 | + <bundle>mvn:io.netty/netty-codec/4.1.0.Beta6</bundle> | ||
27 | + <bundle>mvn:io.netty/netty-codec-http/4.1.0.Beta6</bundle> | ||
28 | + <bundle>mvn:io.netty/netty-codec-http2/4.1.0.Beta6</bundle> | ||
29 | + <bundle>mvn:io.netty/netty-resolver/4.1.0.Beta6</bundle> | ||
30 | + <bundle>mvn:com.twitter/hpack/0.11.0</bundle> | ||
31 | + <!-- TODO: Create shaded jar for these. --> | ||
32 | + <bundle>wrap:mvn:com.google.auth/google-auth-library-credentials/0.3.0$Bundle-SymbolicName=com.google.auth.google-auth-library-credentials&Bundle-Version=0.3.0</bundle> | ||
33 | + <bundle>wrap:mvn:com.google.auth/google-auth-library-oauth2-http/0.3.0$Bundle-SymbolicName=com.google.auth.google-auth-library-oauth2-http&Bundle-Version=0.3.0</bundle> | ||
34 | + <bundle>wrap:mvn:io.grpc/grpc-all/0.9.0$Bundle-SymbolicName=io.grpc.grpc-all&Bundle-Version=0.9.0&Import-Package=io.netty.*;version=4.1.0.Beta6,javax.net.ssl,com.google.protobuf.nano;resolution:=optional,okio;resolution:=optional,*</bundle> | ||
35 | + <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle> | ||
36 | + </feature> | ||
37 | +</features> |
incubator/rpc-grpc/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
18 | + <modelVersion>4.0.0</modelVersion> | ||
19 | + <parent> | ||
20 | + <artifactId>onos-incubator</artifactId> | ||
21 | + <groupId>org.onosproject</groupId> | ||
22 | + <version>1.4.0-SNAPSHOT</version> | ||
23 | + </parent> | ||
24 | + | ||
25 | + <artifactId>onos-incubator-rpc-grpc</artifactId> | ||
26 | + <packaging>bundle</packaging> | ||
27 | + | ||
28 | + <description>ONOS inter-cluster RPC based on gRPC</description> | ||
29 | + <url>http://onosproject.org</url> | ||
30 | + | ||
31 | + <properties> | ||
32 | + <onos.app.name>org.onosproject.incubator.rpc.grpc</onos.app.name> | ||
33 | + <onos.app.requires>org.onosproject.incubator.rpc</onos.app.requires> | ||
34 | + <!-- Note: update feature.xml when updating --> | ||
35 | + <grpc.version>0.9.0</grpc.version> | ||
36 | + <grpc.netty.version>4.1.0.Beta6</grpc.netty.version> | ||
37 | + </properties> | ||
38 | + | ||
39 | + <pluginRepositories> | ||
40 | + <pluginRepository> | ||
41 | + <id>protoc-plugin</id> | ||
42 | + <url>https://dl.bintray.com/sergei-ivanov/maven/</url> | ||
43 | + </pluginRepository> | ||
44 | + </pluginRepositories> | ||
45 | + | ||
46 | + | ||
47 | + <dependencies> | ||
48 | + <dependency> | ||
49 | + <groupId>org.onosproject</groupId> | ||
50 | + <artifactId>onos-api</artifactId> | ||
51 | + </dependency> | ||
52 | + | ||
53 | + <dependency> | ||
54 | + <groupId>org.onosproject</groupId> | ||
55 | + <artifactId>onos-incubator-api</artifactId> | ||
56 | + </dependency> | ||
57 | + | ||
58 | + <dependency> | ||
59 | + <groupId>org.onosproject</groupId> | ||
60 | + <artifactId>onlab-osgi</artifactId> | ||
61 | + </dependency> | ||
62 | +<!-- | ||
63 | + <dependency> | ||
64 | + <groupId>io.grpc</groupId> | ||
65 | + <artifactId>grpc-all</artifactId> | ||
66 | + <version>${grpc.version}</version> | ||
67 | + </dependency> | ||
68 | +--> | ||
69 | + <dependency> | ||
70 | + <groupId>io.grpc</groupId> | ||
71 | + <artifactId>grpc-core</artifactId> | ||
72 | + <version>${grpc.version}</version> | ||
73 | + </dependency> | ||
74 | + <dependency> | ||
75 | + <groupId>io.grpc</groupId> | ||
76 | + <artifactId>grpc-protobuf</artifactId> | ||
77 | + <version>${grpc.version}</version> | ||
78 | + </dependency> | ||
79 | + <dependency> | ||
80 | + <groupId>io.grpc</groupId> | ||
81 | + <artifactId>grpc-stub</artifactId> | ||
82 | + <version>${grpc.version}</version> | ||
83 | + </dependency> | ||
84 | + <dependency> | ||
85 | + <groupId>io.grpc</groupId> | ||
86 | + <artifactId>grpc-netty</artifactId> | ||
87 | + <version>${grpc.version}</version> | ||
88 | + </dependency> | ||
89 | + <dependency> | ||
90 | + <groupId>io.grpc</groupId> | ||
91 | + <artifactId>grpc-auth</artifactId> | ||
92 | + <version>${grpc.version}</version> | ||
93 | + </dependency> | ||
94 | + | ||
95 | + <dependency> | ||
96 | + <groupId>junit</groupId> | ||
97 | + <artifactId>junit</artifactId> | ||
98 | + <scope>test</scope> | ||
99 | + </dependency> | ||
100 | + | ||
101 | + <dependency> | ||
102 | + <groupId>org.onosproject</groupId> | ||
103 | + <artifactId>onos-api</artifactId> | ||
104 | + <scope>test</scope> | ||
105 | + <classifier>tests</classifier> | ||
106 | + </dependency> | ||
107 | + | ||
108 | + <dependency> | ||
109 | + <groupId>org.apache.felix</groupId> | ||
110 | + <artifactId>org.apache.felix.scr.annotations</artifactId> | ||
111 | + <scope>provided</scope> | ||
112 | + </dependency> | ||
113 | + </dependencies> | ||
114 | + | ||
115 | + <build> | ||
116 | + <extensions> | ||
117 | + <extension> | ||
118 | + <groupId>kr.motd.maven</groupId> | ||
119 | + <artifactId>os-maven-plugin</artifactId> | ||
120 | + <version>1.4.0.Final</version> | ||
121 | + </extension> | ||
122 | + </extensions> | ||
123 | + | ||
124 | + <plugins> | ||
125 | + <plugin> | ||
126 | + <groupId>org.apache.felix</groupId> | ||
127 | + <artifactId>maven-bundle-plugin</artifactId> | ||
128 | + <extensions>true</extensions> | ||
129 | + </plugin> | ||
130 | + <plugin> | ||
131 | + <groupId>org.apache.maven.plugins</groupId> | ||
132 | + <artifactId>maven-compiler-plugin</artifactId> | ||
133 | + <configuration> | ||
134 | + <source>1.8</source> | ||
135 | + <target>1.8</target> | ||
136 | + </configuration> | ||
137 | + </plugin> | ||
138 | + <plugin> | ||
139 | + <groupId>org.apache.felix</groupId> | ||
140 | + <artifactId>maven-scr-plugin</artifactId> | ||
141 | + <executions> | ||
142 | + <execution> | ||
143 | + <id>generate-scr-srcdescriptor</id> | ||
144 | + <goals> | ||
145 | + <goal>scr</goal> | ||
146 | + </goals> | ||
147 | + </execution> | ||
148 | + </executions> | ||
149 | + <configuration> | ||
150 | + <!-- avoid searching into wrong source path --> | ||
151 | + <scanClasses>true</scanClasses> | ||
152 | + <supportedProjectTypes> | ||
153 | + <supportedProjectType>bundle</supportedProjectType> | ||
154 | + <supportedProjectType>war</supportedProjectType> | ||
155 | + </supportedProjectTypes> | ||
156 | + </configuration> | ||
157 | + </plugin> | ||
158 | + <plugin> | ||
159 | + <groupId>org.onosproject</groupId> | ||
160 | + <artifactId>onos-maven-plugin</artifactId> | ||
161 | + <executions> | ||
162 | + <execution> | ||
163 | + <id>cfg</id> | ||
164 | + <phase>generate-resources</phase> | ||
165 | + <goals> | ||
166 | + <goal>cfg</goal> | ||
167 | + </goals> | ||
168 | + </execution> | ||
169 | + <execution> | ||
170 | + <id>swagger</id> | ||
171 | + <phase>generate-sources</phase> | ||
172 | + <goals> | ||
173 | + <goal>swagger</goal> | ||
174 | + </goals> | ||
175 | + </execution> | ||
176 | + <execution> | ||
177 | + <id>app</id> | ||
178 | + <phase>package</phase> | ||
179 | + <goals> | ||
180 | + <goal>app</goal> | ||
181 | + </goals> | ||
182 | + </execution> | ||
183 | + </executions> | ||
184 | + </plugin> | ||
185 | + | ||
186 | + <plugin> | ||
187 | + <groupId>com.google.protobuf.tools</groupId> | ||
188 | + <artifactId>maven-protoc-plugin</artifactId> | ||
189 | + <version>0.4.2</version> | ||
190 | + <configuration> | ||
191 | + <!-- The version of protoc must match protobuf-java. If you don't | ||
192 | + depend on protobuf-java directly, you will be transitively depending on the | ||
193 | + protobuf-java version that grpc depends on. --> | ||
194 | + <protocArtifact>com.google.protobuf:protoc:3.0.0-beta-1:exe:${os.detected.classifier}</protocArtifact> | ||
195 | + <pluginId>grpc-java</pluginId> | ||
196 | + <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact> | ||
197 | + </configuration> | ||
198 | + <executions> | ||
199 | + <execution> | ||
200 | + <goals> | ||
201 | + <goal>compile</goal> | ||
202 | + <goal>compile-custom</goal> | ||
203 | + </goals> | ||
204 | + </execution> | ||
205 | + </executions> | ||
206 | + </plugin> | ||
207 | + | ||
208 | + <plugin> | ||
209 | + <groupId>org.codehaus.mojo</groupId> | ||
210 | + <artifactId>build-helper-maven-plugin</artifactId> | ||
211 | + <version>1.9.1</version> | ||
212 | + <executions> | ||
213 | + <execution> | ||
214 | + <id>add-source</id> | ||
215 | + <phase>generate-sources</phase> | ||
216 | + <goals> | ||
217 | + <goal>add-source</goal> | ||
218 | + </goals> | ||
219 | + <configuration> | ||
220 | + <sources> | ||
221 | + <source>${project.build.directory}/generated-sources/protobuf/java</source> | ||
222 | + <source>${project.build.directory}/generated-sources/protobuf/grpc-java</source> | ||
223 | + </sources> | ||
224 | + </configuration> | ||
225 | + </execution> | ||
226 | + </executions> | ||
227 | + </plugin> | ||
228 | + | ||
229 | + </plugins> | ||
230 | + </build> | ||
231 | + | ||
232 | + <!-- gRPC requires more recent version of netty --> | ||
233 | + <dependencyManagement> | ||
234 | + <dependencies> | ||
235 | + <dependency> | ||
236 | + <groupId>io.netty</groupId> | ||
237 | + <artifactId>netty-codec</artifactId> | ||
238 | + <version>${grpc.netty.version}</version> | ||
239 | + </dependency> | ||
240 | + <dependency> | ||
241 | + <groupId>io.netty</groupId> | ||
242 | + <artifactId>netty-transport</artifactId> | ||
243 | + <version>${grpc.netty.version}</version> | ||
244 | + </dependency> | ||
245 | + <dependency> | ||
246 | + <groupId>io.netty</groupId> | ||
247 | + <artifactId>netty-handler</artifactId> | ||
248 | + <version>${grpc.netty.version}</version> | ||
249 | + </dependency> | ||
250 | + <dependency> | ||
251 | + <groupId>io.netty</groupId> | ||
252 | + <artifactId>netty-buffer</artifactId> | ||
253 | + <version>${grpc.netty.version}</version> | ||
254 | + </dependency> | ||
255 | + <dependency> | ||
256 | + <groupId>io.netty</groupId> | ||
257 | + <artifactId>netty-common</artifactId> | ||
258 | + <version>${grpc.netty.version}</version> | ||
259 | + </dependency> | ||
260 | + <dependency> | ||
261 | + <groupId>com.twitter</groupId> | ||
262 | + <artifactId>hpack</artifactId> | ||
263 | + <!-- 0.11.0 and later are published as a bundle --> | ||
264 | + <version>0.11.0</version> | ||
265 | + </dependency> | ||
266 | + </dependencies> | ||
267 | + </dependencyManagement> | ||
268 | + | ||
269 | +</project> |
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 java.util.Map; | ||
19 | + | ||
20 | +import org.onosproject.net.device.DeviceProvider; | ||
21 | +import org.onosproject.net.device.DeviceProviderRegistry; | ||
22 | +import org.onosproject.net.device.DeviceProviderService; | ||
23 | +import org.onosproject.net.provider.AbstractProviderRegistry; | ||
24 | +import org.slf4j.Logger; | ||
25 | +import org.slf4j.LoggerFactory; | ||
26 | + | ||
27 | +import com.google.common.collect.Maps; | ||
28 | + | ||
29 | +import io.grpc.Channel; | ||
30 | +import io.grpc.ManagedChannel; | ||
31 | + | ||
32 | +// gRPC Client side | ||
33 | +/** | ||
34 | + * Proxy object to handle DeviceProviderRegistry calls. | ||
35 | + * | ||
36 | + * RPC wise, this will start/stop bidirectional streaming service sessions. | ||
37 | + */ | ||
38 | +final class DeviceProviderRegistryClientProxy | ||
39 | + extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService> | ||
40 | + implements DeviceProviderRegistry { | ||
41 | + | ||
42 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
43 | + | ||
44 | + private final Channel channel; | ||
45 | + | ||
46 | + private final Map<DeviceProvider, DeviceProviderServiceClientProxy> pServices; | ||
47 | + | ||
48 | + DeviceProviderRegistryClientProxy(ManagedChannel channel) { | ||
49 | + this.channel = channel; | ||
50 | + pServices = Maps.newIdentityHashMap(); | ||
51 | + } | ||
52 | + | ||
53 | + @Override | ||
54 | + protected synchronized DeviceProviderService createProviderService(DeviceProvider provider) { | ||
55 | + | ||
56 | + // Create session | ||
57 | + DeviceProviderServiceClientProxy pService = new DeviceProviderServiceClientProxy(provider, channel); | ||
58 | + log.debug("Created DeviceProviderServiceClientProxy", pService); | ||
59 | + | ||
60 | + DeviceProviderServiceClientProxy old = pServices.put(provider, pService); | ||
61 | + if (old != null) { | ||
62 | + // sanity check, can go away | ||
63 | + log.warn("Duplicate registration detected for {}", provider.id()); | ||
64 | + } | ||
65 | + return pService; | ||
66 | + } | ||
67 | + | ||
68 | + @Override | ||
69 | + public synchronized void unregister(DeviceProvider provider) { | ||
70 | + DeviceProviderServiceClientProxy pService = pServices.remove(provider); | ||
71 | + log.debug("Unregistering DeviceProviderServiceClientProxy", pService); | ||
72 | + super.unregister(provider); | ||
73 | + if (pService != null) { | ||
74 | + pService.shutdown(); | ||
75 | + } | ||
76 | + } | ||
77 | +} |
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 | +import static java.util.stream.Collectors.toList; | ||
20 | +import static org.onosproject.incubator.rpc.grpc.GrpcDeviceUtils.translate; | ||
21 | +import static org.onosproject.net.DeviceId.deviceId; | ||
22 | + | ||
23 | +import java.util.Collection; | ||
24 | +import java.util.List; | ||
25 | +import java.util.concurrent.atomic.AtomicBoolean; | ||
26 | + | ||
27 | +import org.onosproject.grpc.Device.DeviceProviderMsg; | ||
28 | +import org.onosproject.grpc.Device.DeviceProviderServiceMsg; | ||
29 | +import org.onosproject.grpc.Device.IsReachableRequest; | ||
30 | +import org.onosproject.grpc.Device.RoleChanged; | ||
31 | +import org.onosproject.grpc.Device.TriggerProbe; | ||
32 | +import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc; | ||
33 | +import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc.DeviceProviderRegistryRpcStub; | ||
34 | +import org.onosproject.net.DeviceId; | ||
35 | +import org.onosproject.net.MastershipRole; | ||
36 | +import org.onosproject.net.device.DeviceDescription; | ||
37 | +import org.onosproject.net.device.DeviceProvider; | ||
38 | +import org.onosproject.net.device.DeviceProviderService; | ||
39 | +import org.onosproject.net.device.PortDescription; | ||
40 | +import org.onosproject.net.device.PortStatistics; | ||
41 | +import org.onosproject.net.provider.AbstractProviderService; | ||
42 | +import org.slf4j.Logger; | ||
43 | +import org.slf4j.LoggerFactory; | ||
44 | + | ||
45 | +import com.google.common.base.MoreObjects; | ||
46 | + | ||
47 | +import io.grpc.Channel; | ||
48 | +import io.grpc.stub.StreamObserver; | ||
49 | + | ||
50 | +// gRPC Client side | ||
51 | +// gRPC wise, this object represents bidirectional streaming service session | ||
52 | +// and deals with outgoing message stream | ||
53 | +/** | ||
54 | + * DeviceProviderService instance associated with given DeviceProvider. | ||
55 | + */ | ||
56 | +final class DeviceProviderServiceClientProxy | ||
57 | + extends AbstractProviderService<DeviceProvider> | ||
58 | + implements DeviceProviderService { | ||
59 | + | ||
60 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
61 | + | ||
62 | + private final StreamObserver<DeviceProviderServiceMsg> devProvService; | ||
63 | + private final AtomicBoolean hasShutdown = new AtomicBoolean(false); | ||
64 | + | ||
65 | + private final Channel channel; | ||
66 | + | ||
67 | + DeviceProviderServiceClientProxy(DeviceProvider provider, Channel channel) { | ||
68 | + super(provider); | ||
69 | + this.channel = channel; | ||
70 | + | ||
71 | + DeviceProviderRegistryRpcStub stub = DeviceProviderRegistryRpcGrpc.newStub(channel); | ||
72 | + log.debug("Calling RPC register({}) against {}", provider.id(), channel.authority()); | ||
73 | + devProvService = stub.register(new DeviceProviderClientProxy(provider)); | ||
74 | + | ||
75 | + // send initialize message | ||
76 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
77 | + builder.setRegisterProvider(builder.getRegisterProviderBuilder() | ||
78 | + .setProviderScheme(provider.id().scheme()) | ||
79 | + .build()); | ||
80 | + devProvService.onNext(builder.build()); | ||
81 | + } | ||
82 | + | ||
83 | + @Override | ||
84 | + public void deviceConnected(DeviceId deviceId, | ||
85 | + DeviceDescription deviceDescription) { | ||
86 | + checkValidity(); | ||
87 | + | ||
88 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
89 | + builder.setDeviceConnected(builder.getDeviceConnectedBuilder() | ||
90 | + .setDeviceId(deviceId.toString()) | ||
91 | + .setDeviceDescription(translate(deviceDescription)) | ||
92 | + .build()); | ||
93 | + | ||
94 | + devProvService.onNext(builder.build()); | ||
95 | + } | ||
96 | + | ||
97 | + @Override | ||
98 | + public void deviceDisconnected(DeviceId deviceId) { | ||
99 | + checkValidity(); | ||
100 | + | ||
101 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
102 | + builder.setDeviceDisconnected(builder.getDeviceDisconnectedBuilder() | ||
103 | + .setDeviceId(deviceId.toString()) | ||
104 | + .build()); | ||
105 | + | ||
106 | + devProvService.onNext(builder.build()); | ||
107 | + } | ||
108 | + | ||
109 | + @Override | ||
110 | + public void updatePorts(DeviceId deviceId, | ||
111 | + List<PortDescription> portDescriptions) { | ||
112 | + checkValidity(); | ||
113 | + | ||
114 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
115 | + List<org.onosproject.grpc.Port.PortDescription> portDescs = | ||
116 | + portDescriptions.stream() | ||
117 | + .map(GrpcDeviceUtils::translate) | ||
118 | + .collect(toList()); | ||
119 | + | ||
120 | + builder.setUpdatePorts(builder.getUpdatePortsBuilder() | ||
121 | + .setDeviceId(deviceId.toString()) | ||
122 | + .addAllPortDescriptions(portDescs) | ||
123 | + .build()); | ||
124 | + | ||
125 | + devProvService.onNext(builder.build()); | ||
126 | + } | ||
127 | + | ||
128 | + @Override | ||
129 | + public void portStatusChanged(DeviceId deviceId, | ||
130 | + PortDescription portDescription) { | ||
131 | + checkValidity(); | ||
132 | + | ||
133 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
134 | + builder.setPortStatusChanged(builder.getPortStatusChangedBuilder() | ||
135 | + .setDeviceId(deviceId.toString()) | ||
136 | + .setPortDescription(translate(portDescription)) | ||
137 | + .build()); | ||
138 | + | ||
139 | + devProvService.onNext(builder.build()); | ||
140 | + } | ||
141 | + | ||
142 | + @Override | ||
143 | + public void receivedRoleReply(DeviceId deviceId, MastershipRole requested, | ||
144 | + MastershipRole response) { | ||
145 | + checkValidity(); | ||
146 | + | ||
147 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
148 | + builder.setReceivedRoleReply(builder.getReceivedRoleReplyBuilder() | ||
149 | + .setDeviceId(deviceId.toString()) | ||
150 | + .setRequested(translate(requested)) | ||
151 | + .setResponse(translate(response)) | ||
152 | + .build()); | ||
153 | + | ||
154 | + devProvService.onNext(builder.build()); | ||
155 | + } | ||
156 | + | ||
157 | + @Override | ||
158 | + public void updatePortStatistics(DeviceId deviceId, | ||
159 | + Collection<PortStatistics> portStatistics) { | ||
160 | + checkValidity(); | ||
161 | + | ||
162 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
163 | + List<org.onosproject.grpc.Port.PortStatistics> portStats = | ||
164 | + portStatistics.stream() | ||
165 | + .map(GrpcDeviceUtils::translate) | ||
166 | + .collect(toList()); | ||
167 | + builder.setUpdatePortStatistics(builder.getUpdatePortStatisticsBuilder() | ||
168 | + .setDeviceId(deviceId.toString()) | ||
169 | + .addAllPortStatistics(portStats) | ||
170 | + .build()); | ||
171 | + | ||
172 | + devProvService.onNext(builder.build()); | ||
173 | + } | ||
174 | + | ||
175 | + /** | ||
176 | + * Shutdown this session. | ||
177 | + */ | ||
178 | + public void shutdown() { | ||
179 | + if (hasShutdown.compareAndSet(false, true)) { | ||
180 | + log.info("Shutting down session over {}", channel.authority()); | ||
181 | + // initiate clean shutdown from client | ||
182 | + devProvService.onCompleted(); | ||
183 | + invalidate(); | ||
184 | + } | ||
185 | + } | ||
186 | + | ||
187 | + /** | ||
188 | + * Abnormally terminate this session. | ||
189 | + * @param t error details | ||
190 | + */ | ||
191 | + public void shutdown(Throwable t) { | ||
192 | + if (hasShutdown.compareAndSet(false, true)) { | ||
193 | + log.error("Shutting down session over {}", channel.authority()); | ||
194 | + // initiate abnormal termination from client | ||
195 | + devProvService.onError(t); | ||
196 | + invalidate(); | ||
197 | + } | ||
198 | + } | ||
199 | + | ||
200 | + @Override | ||
201 | + public String toString() { | ||
202 | + return MoreObjects.toStringHelper(this) | ||
203 | + .add("channel", channel.authority()) | ||
204 | + .add("hasShutdown", hasShutdown.get()) | ||
205 | + .toString(); | ||
206 | + } | ||
207 | + | ||
208 | + // gRPC wise, this object handles incoming message stream | ||
209 | + /** | ||
210 | + * Translates DeviceProvider instructions received from RPC to Java calls. | ||
211 | + */ | ||
212 | + private final class DeviceProviderClientProxy | ||
213 | + implements StreamObserver<DeviceProviderMsg> { | ||
214 | + | ||
215 | + private final DeviceProvider provider; | ||
216 | + | ||
217 | + DeviceProviderClientProxy(DeviceProvider provider) { | ||
218 | + this.provider = checkNotNull(provider); | ||
219 | + } | ||
220 | + | ||
221 | + @Override | ||
222 | + public void onNext(DeviceProviderMsg msg) { | ||
223 | + try { | ||
224 | + log.trace("DeviceProviderClientProxy received: {}", msg); | ||
225 | + onMethod(msg); | ||
226 | + } catch (Exception e) { | ||
227 | + log.error("Exception caught handling {} at DeviceProviderClientProxy", msg, e); | ||
228 | + // initiate shutdown from client | ||
229 | + shutdown(e); | ||
230 | + } | ||
231 | + } | ||
232 | + | ||
233 | + /** | ||
234 | + * Translates received RPC message to {@link DeviceProvider} method calls. | ||
235 | + * @param msg DeviceProvider message | ||
236 | + */ | ||
237 | + private void onMethod(DeviceProviderMsg msg) { | ||
238 | + switch (msg.getMethodCase()) { | ||
239 | + case TRIGGER_PROBE: | ||
240 | + TriggerProbe triggerProbe = msg.getTriggerProbe(); | ||
241 | + provider.triggerProbe(deviceId(triggerProbe.getDeviceId())); | ||
242 | + break; | ||
243 | + case ROLE_CHANGED: | ||
244 | + RoleChanged roleChanged = msg.getRoleChanged(); | ||
245 | + provider.roleChanged(deviceId(roleChanged.getDeviceId()), | ||
246 | + translate(roleChanged.getNewRole())); | ||
247 | + break; | ||
248 | + case IS_REACHABLE_REQUEST: | ||
249 | + IsReachableRequest isReachableRequest = msg.getIsReachableRequest(); | ||
250 | + // check if reachable | ||
251 | + boolean reachable = provider.isReachable(deviceId(isReachableRequest.getDeviceId())); | ||
252 | + | ||
253 | + int xid = isReachableRequest.getXid(); | ||
254 | + // send response back DeviceProviderService channel | ||
255 | + DeviceProviderServiceMsg.Builder builder = DeviceProviderServiceMsg.newBuilder(); | ||
256 | + builder.setIsReachableResponse(builder.getIsReachableResponseBuilder() | ||
257 | + .setXid(xid) | ||
258 | + .setIsReachable(reachable) | ||
259 | + .build()); | ||
260 | + devProvService.onNext(builder.build()); | ||
261 | + break; | ||
262 | + | ||
263 | + case METHOD_NOT_SET: | ||
264 | + default: | ||
265 | + log.warn("Unexpected method, ignoring", msg); | ||
266 | + break; | ||
267 | + } | ||
268 | + } | ||
269 | + | ||
270 | + @Override | ||
271 | + public void onCompleted() { | ||
272 | + log.info("DeviceProviderClientProxy completed"); | ||
273 | + // session terminated from remote | ||
274 | + // TODO unregister...? how? | ||
275 | + | ||
276 | + //devProvService.onCompleted(); | ||
277 | + } | ||
278 | + | ||
279 | + @Override | ||
280 | + public void onError(Throwable t) { | ||
281 | + log.error("DeviceProviderClientProxy#onError", t); | ||
282 | + // session terminated from remote | ||
283 | + // TODO unregister...? how? | ||
284 | + //devProvService.onError(t); | ||
285 | + } | ||
286 | + | ||
287 | + @Override | ||
288 | + public String toString() { | ||
289 | + return MoreObjects.toStringHelper(this) | ||
290 | + .add("channel", channel.authority()) | ||
291 | + .toString(); | ||
292 | + } | ||
293 | + } | ||
294 | +} | ||
295 | + |
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 java.net.URI; | ||
19 | +import java.util.HashMap; | ||
20 | +import java.util.Map; | ||
21 | + | ||
22 | +import org.onlab.packet.ChassisId; | ||
23 | +import org.onosproject.grpc.Device.DeviceType; | ||
24 | +import org.onosproject.grpc.Port.PortType; | ||
25 | +import org.onosproject.net.Annotations; | ||
26 | +import org.onosproject.net.DefaultAnnotations; | ||
27 | +import org.onosproject.net.Device; | ||
28 | +import org.onosproject.net.MastershipRole; | ||
29 | +import org.onosproject.net.Port; | ||
30 | +import org.onosproject.net.Port.Type; | ||
31 | +import org.onosproject.net.PortNumber; | ||
32 | +import org.onosproject.net.SparseAnnotations; | ||
33 | +import org.onosproject.net.device.DefaultDeviceDescription; | ||
34 | +import org.onosproject.net.device.DefaultPortDescription; | ||
35 | +import org.onosproject.net.device.DefaultPortStatistics; | ||
36 | +import org.onosproject.net.device.DeviceDescription; | ||
37 | +import org.onosproject.net.device.PortDescription; | ||
38 | +import org.onosproject.net.device.PortStatistics; | ||
39 | +import org.slf4j.Logger; | ||
40 | +import org.slf4j.LoggerFactory; | ||
41 | + | ||
42 | +import com.google.api.client.repackaged.com.google.common.annotations.Beta; | ||
43 | + | ||
44 | +/** | ||
45 | + * gRPC message conversion related utilities. | ||
46 | + */ | ||
47 | +@Beta | ||
48 | +public final class GrpcDeviceUtils { | ||
49 | + | ||
50 | + private static final Logger log = LoggerFactory.getLogger(GrpcDeviceUtils.class); | ||
51 | + | ||
52 | + /** | ||
53 | + * Translates gRPC enum MastershipRole to ONOS enum. | ||
54 | + * | ||
55 | + * @param role mastership role in gRPC enum | ||
56 | + * @return equivalent in ONOS enum | ||
57 | + */ | ||
58 | + public static MastershipRole translate(org.onosproject.grpc.Device.MastershipRole role) { | ||
59 | + switch (role) { | ||
60 | + case NONE: | ||
61 | + return MastershipRole.NONE; | ||
62 | + case MASTER: | ||
63 | + return MastershipRole.MASTER; | ||
64 | + case STANDBY: | ||
65 | + return MastershipRole.STANDBY; | ||
66 | + case UNRECOGNIZED: | ||
67 | + log.warn("Unrecognized MastershipRole gRPC message: {}", role); | ||
68 | + default: | ||
69 | + return MastershipRole.NONE; | ||
70 | + } | ||
71 | + } | ||
72 | + | ||
73 | + /** | ||
74 | + * Translates ONOS enum MastershipRole to gRPC enum. | ||
75 | + * | ||
76 | + * @param newRole ONOS' mastership role | ||
77 | + * @return equivalent in gRPC message enum | ||
78 | + */ | ||
79 | + public static org.onosproject.grpc.Device.MastershipRole translate(MastershipRole newRole) { | ||
80 | + switch (newRole) { | ||
81 | + case MASTER: | ||
82 | + return org.onosproject.grpc.Device.MastershipRole.MASTER; | ||
83 | + case STANDBY: | ||
84 | + return org.onosproject.grpc.Device.MastershipRole.STANDBY; | ||
85 | + case NONE: | ||
86 | + default: | ||
87 | + return org.onosproject.grpc.Device.MastershipRole.NONE; | ||
88 | + } | ||
89 | + } | ||
90 | + | ||
91 | + | ||
92 | + /** | ||
93 | + * Translates gRPC DeviceDescription to {@link DeviceDescription}. | ||
94 | + * | ||
95 | + * @param deviceDescription gRPC message | ||
96 | + * @return {@link DeviceDescription} | ||
97 | + */ | ||
98 | + public static DeviceDescription translate(org.onosproject.grpc.Device.DeviceDescription deviceDescription) { | ||
99 | + URI uri = URI.create(deviceDescription.getDeviceUri()); | ||
100 | + Device.Type type = translate(deviceDescription.getType()); | ||
101 | + String manufacturer = deviceDescription.getManufacturer(); | ||
102 | + String hwVersion = deviceDescription.getHwVersion(); | ||
103 | + String swVersion = deviceDescription.getSwVersion(); | ||
104 | + String serialNumber = deviceDescription.getSerialNumber(); | ||
105 | + ChassisId chassis = new ChassisId(deviceDescription.getChassisId()); | ||
106 | + return new DefaultDeviceDescription(uri, type, manufacturer, | ||
107 | + hwVersion, swVersion, serialNumber, | ||
108 | + chassis, | ||
109 | + asAnnotations(deviceDescription.getAnnotations())); | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * Translates {@link DeviceDescription} to gRPC DeviceDescription message. | ||
114 | + * | ||
115 | + * @param deviceDescription {@link DeviceDescription} | ||
116 | + * @return gRPC DeviceDescription message | ||
117 | + */ | ||
118 | + public static org.onosproject.grpc.Device.DeviceDescription translate(DeviceDescription deviceDescription) { | ||
119 | + | ||
120 | + return org.onosproject.grpc.Device.DeviceDescription.newBuilder() | ||
121 | + .setDeviceUri(deviceDescription.deviceUri().toString()) | ||
122 | + .setType(translate(deviceDescription.type())) | ||
123 | + .setManufacturer(deviceDescription.manufacturer()) | ||
124 | + .setHwVersion(deviceDescription.hwVersion()) | ||
125 | + .setSwVersion(deviceDescription.swVersion()) | ||
126 | + .setSerialNumber(deviceDescription.serialNumber()) | ||
127 | + .setChassisId(deviceDescription.chassisId().toString()) | ||
128 | + .putAllAnnotations(asMap(deviceDescription.annotations())) | ||
129 | + .build(); | ||
130 | + } | ||
131 | + | ||
132 | + | ||
133 | + /** | ||
134 | + * Translates gRPC DeviceType to {@link Device.Type}. | ||
135 | + * | ||
136 | + * @param type gRPC message | ||
137 | + * @return {@link Device.Type} | ||
138 | + */ | ||
139 | + public static Device.Type translate(org.onosproject.grpc.Device.DeviceType type) { | ||
140 | + switch (type) { | ||
141 | + case BALANCER: | ||
142 | + return Device.Type.BALANCER; | ||
143 | + case CONTROLLER: | ||
144 | + return Device.Type.CONTROLLER; | ||
145 | + case FIBER_SWITCH: | ||
146 | + return Device.Type.FIBER_SWITCH; | ||
147 | + case FIREWALL: | ||
148 | + return Device.Type.FIREWALL; | ||
149 | + case IDS: | ||
150 | + return Device.Type.IDS; | ||
151 | + case IPS: | ||
152 | + return Device.Type.IPS; | ||
153 | + case MICROWAVE: | ||
154 | + return Device.Type.MICROWAVE; | ||
155 | + case OTHER: | ||
156 | + return Device.Type.OTHER; | ||
157 | + case OTN: | ||
158 | + return Device.Type.OTN; | ||
159 | + case ROADM: | ||
160 | + return Device.Type.ROADM; | ||
161 | + case ROADM_OTN: | ||
162 | + return Device.Type.ROADM_OTN; | ||
163 | + case ROUTER: | ||
164 | + return Device.Type.ROUTER; | ||
165 | + case SWITCH: | ||
166 | + return Device.Type.SWITCH; | ||
167 | + case VIRTUAL: | ||
168 | + return Device.Type.VIRTUAL; | ||
169 | + | ||
170 | + case UNRECOGNIZED: | ||
171 | + default: | ||
172 | + log.warn("Unexpected DeviceType: {}", type); | ||
173 | + return Device.Type.OTHER; | ||
174 | + } | ||
175 | + } | ||
176 | + | ||
177 | + /** | ||
178 | + * Translates {@link Type} to gRPC DeviceType. | ||
179 | + * | ||
180 | + * @param type {@link Type} | ||
181 | + * @return gRPC message | ||
182 | + */ | ||
183 | + public static DeviceType translate(Device.Type type) { | ||
184 | + switch (type) { | ||
185 | + case BALANCER: | ||
186 | + return DeviceType.BALANCER; | ||
187 | + case CONTROLLER: | ||
188 | + return DeviceType.CONTROLLER; | ||
189 | + case FIBER_SWITCH: | ||
190 | + return DeviceType.FIBER_SWITCH; | ||
191 | + case FIREWALL: | ||
192 | + return DeviceType.FIREWALL; | ||
193 | + case IDS: | ||
194 | + return DeviceType.IDS; | ||
195 | + case IPS: | ||
196 | + return DeviceType.IPS; | ||
197 | + case MICROWAVE: | ||
198 | + return DeviceType.MICROWAVE; | ||
199 | + case OTHER: | ||
200 | + return DeviceType.OTHER; | ||
201 | + case OTN: | ||
202 | + return DeviceType.OTN; | ||
203 | + case ROADM: | ||
204 | + return DeviceType.ROADM; | ||
205 | + case ROADM_OTN: | ||
206 | + return DeviceType.ROADM_OTN; | ||
207 | + case ROUTER: | ||
208 | + return DeviceType.ROUTER; | ||
209 | + case SWITCH: | ||
210 | + return DeviceType.SWITCH; | ||
211 | + case VIRTUAL: | ||
212 | + return DeviceType.VIRTUAL; | ||
213 | + | ||
214 | + default: | ||
215 | + log.warn("Unexpected Device.Type: {}", type); | ||
216 | + return DeviceType.OTHER; | ||
217 | + } | ||
218 | + } | ||
219 | + | ||
220 | + /** | ||
221 | + * Translates gRPC PortDescription message to {@link PortDescription}. | ||
222 | + * | ||
223 | + * @param portDescription gRPC message | ||
224 | + * @return {@link PortDescription} | ||
225 | + */ | ||
226 | + public static PortDescription translate(org.onosproject.grpc.Port.PortDescription portDescription) { | ||
227 | + PortNumber number = PortNumber.fromString(portDescription.getPortNumber()); | ||
228 | + boolean isEnabled = portDescription.getIsEnabled(); | ||
229 | + Port.Type type = translate(portDescription.getType()); | ||
230 | + long portSpeed = portDescription.getPortSpeed(); | ||
231 | + SparseAnnotations annotations = asAnnotations(portDescription.getAnnotations()); | ||
232 | + // TODO How to deal with more specific Port... | ||
233 | + return new DefaultPortDescription(number, isEnabled, type, portSpeed, annotations); | ||
234 | + } | ||
235 | + | ||
236 | + /** | ||
237 | + * Translates {@link PortDescription} to gRPC PortDescription message. | ||
238 | + * | ||
239 | + * @param portDescription {@link PortDescription} | ||
240 | + * @return gRPC PortDescription message | ||
241 | + */ | ||
242 | + public static org.onosproject.grpc.Port.PortDescription translate(PortDescription portDescription) { | ||
243 | + // TODO How to deal with more specific Port... | ||
244 | + return org.onosproject.grpc.Port.PortDescription.newBuilder() | ||
245 | + .setPortNumber(portDescription.portNumber().toString()) | ||
246 | + .setIsEnabled(portDescription.isEnabled()) | ||
247 | + .setType(translate(portDescription.type())) | ||
248 | + .setPortSpeed(portDescription.portSpeed()) | ||
249 | + .putAllAnnotations(asMap(portDescription.annotations())) | ||
250 | + .build(); | ||
251 | + } | ||
252 | + | ||
253 | + /** | ||
254 | + * Translates gRPC PortType to {@link Port.Type}. | ||
255 | + * | ||
256 | + * @param type gRPC message | ||
257 | + * @return {@link Port.Type} | ||
258 | + */ | ||
259 | + public static Port.Type translate(PortType type) { | ||
260 | + switch (type) { | ||
261 | + case COPPER: | ||
262 | + return Type.COPPER; | ||
263 | + case FIBER: | ||
264 | + return Type.FIBER; | ||
265 | + case OCH: | ||
266 | + return Type.OCH; | ||
267 | + case ODUCLT: | ||
268 | + return Type.ODUCLT; | ||
269 | + case OMS: | ||
270 | + return Type.OMS; | ||
271 | + case PACKET: | ||
272 | + return Type.PACKET; | ||
273 | + case VIRTUAL: | ||
274 | + return Type.VIRTUAL; | ||
275 | + | ||
276 | + case UNRECOGNIZED: | ||
277 | + default: | ||
278 | + log.warn("Unexpected PortType: {}", type); | ||
279 | + return Type.COPPER; | ||
280 | + } | ||
281 | + } | ||
282 | + | ||
283 | + /** | ||
284 | + * Translates {@link Port.Type} to gRPC PortType. | ||
285 | + * | ||
286 | + * @param type {@link Port.Type} | ||
287 | + * @return gRPC message | ||
288 | + */ | ||
289 | + public static PortType translate(Port.Type type) { | ||
290 | + switch (type) { | ||
291 | + case COPPER: | ||
292 | + return PortType.COPPER; | ||
293 | + case FIBER: | ||
294 | + return PortType.FIBER; | ||
295 | + case OCH: | ||
296 | + return PortType.OCH; | ||
297 | + case ODUCLT: | ||
298 | + return PortType.ODUCLT; | ||
299 | + case OMS: | ||
300 | + return PortType.OMS; | ||
301 | + case PACKET: | ||
302 | + return PortType.PACKET; | ||
303 | + case VIRTUAL: | ||
304 | + return PortType.VIRTUAL; | ||
305 | + | ||
306 | + default: | ||
307 | + log.warn("Unexpected Port.Type: {}", type); | ||
308 | + return PortType.COPPER; | ||
309 | + } | ||
310 | + } | ||
311 | + | ||
312 | + /** | ||
313 | + * Translates gRPC PortStatistics message to {@link PortStatistics}. | ||
314 | + * | ||
315 | + * @param portStatistics gRPC PortStatistics message | ||
316 | + * @return {@link PortStatistics} | ||
317 | + */ | ||
318 | + public static PortStatistics translate(org.onosproject.grpc.Port.PortStatistics portStatistics) { | ||
319 | + // TODO implement adding missing fields | ||
320 | + return DefaultPortStatistics.builder() | ||
321 | + .setPort(portStatistics.getPort()) | ||
322 | + .setPacketsReceived(portStatistics.getPacketsReceived()) | ||
323 | + .setPacketsSent(portStatistics.getPacketsSent()) | ||
324 | + .build(); | ||
325 | + } | ||
326 | + | ||
327 | + /** | ||
328 | + * Translates {@link PortStatistics} to gRPC PortStatistics message. | ||
329 | + * | ||
330 | + * @param portStatistics {@link PortStatistics} | ||
331 | + * @return gRPC PortStatistics message | ||
332 | + */ | ||
333 | + public static org.onosproject.grpc.Port.PortStatistics translate(PortStatistics portStatistics) { | ||
334 | + // TODO implement adding missing fields | ||
335 | + return org.onosproject.grpc.Port.PortStatistics.newBuilder() | ||
336 | + .setPort(portStatistics.port()) | ||
337 | + .setPacketsReceived(portStatistics.packetsReceived()) | ||
338 | + .setPacketsSent(portStatistics.packetsSent()) | ||
339 | + .build(); | ||
340 | + } | ||
341 | + | ||
342 | + // may be this can be moved to Annotation itself or AnnotationsUtils | ||
343 | + /** | ||
344 | + * Converts Annotations to Map of Strings. | ||
345 | + * | ||
346 | + * @param annotations {@link Annotations} | ||
347 | + * @return Map of annotation key and values | ||
348 | + */ | ||
349 | + public static Map<String, String> asMap(Annotations annotations) { | ||
350 | + if (annotations instanceof DefaultAnnotations) { | ||
351 | + return ((DefaultAnnotations) annotations).asMap(); | ||
352 | + } | ||
353 | + Map<String, String> map = new HashMap<>(); | ||
354 | + annotations.keys() | ||
355 | + .forEach(k -> map.put(k, annotations.value(k))); | ||
356 | + | ||
357 | + return map; | ||
358 | + } | ||
359 | + | ||
360 | + // may be this can be moved to Annotation itself or AnnotationsUtils | ||
361 | + /** | ||
362 | + * Converts Map of Strings to {@link SparseAnnotations}. | ||
363 | + * | ||
364 | + * @param annotations Map of annotation key and values | ||
365 | + * @return {@link SparseAnnotations} | ||
366 | + */ | ||
367 | + public static SparseAnnotations asAnnotations(Map<String, String> annotations) { | ||
368 | + DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); | ||
369 | + annotations.entrySet().forEach(e -> { | ||
370 | + if (e.getValue() != null) { | ||
371 | + builder.set(e.getKey(), e.getValue()); | ||
372 | + } else { | ||
373 | + builder.remove(e.getKey()); | ||
374 | + } | ||
375 | + }); | ||
376 | + return builder.build(); | ||
377 | + } | ||
378 | + | ||
379 | + // Utility class not intended for instantiation. | ||
380 | + private GrpcDeviceUtils() {} | ||
381 | +} |
incubator/rpc-grpc/src/main/java/org/onosproject/incubator/rpc/grpc/GrpcRemoteServiceContext.java
0 → 100644
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 java.util.Map; | ||
21 | +import java.util.NoSuchElementException; | ||
22 | +import java.util.concurrent.ConcurrentHashMap; | ||
23 | + | ||
24 | +import org.onosproject.incubator.rpc.RemoteServiceContext; | ||
25 | +import org.onosproject.net.device.DeviceProviderRegistry; | ||
26 | +import org.slf4j.Logger; | ||
27 | +import org.slf4j.LoggerFactory; | ||
28 | + | ||
29 | +import com.google.common.base.MoreObjects; | ||
30 | + | ||
31 | +import io.grpc.ManagedChannel; | ||
32 | + | ||
33 | +// gRPC Client side | ||
34 | +// Probably there should be plug-in mechanism in the future. | ||
35 | +/** | ||
36 | + * RemoteServiceContext based on gRPC. | ||
37 | + * | ||
38 | + * <p> | ||
39 | + * Currently it supports {@link DeviceProviderRegistry}. | ||
40 | + */ | ||
41 | +public class GrpcRemoteServiceContext implements RemoteServiceContext { | ||
42 | + | ||
43 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
44 | + | ||
45 | + private final Map<Class<? extends Object>, Object> services = new ConcurrentHashMap<>(); | ||
46 | + | ||
47 | + private final ManagedChannel channel; | ||
48 | + | ||
49 | + public GrpcRemoteServiceContext(ManagedChannel channel) { | ||
50 | + this.channel = checkNotNull(channel); | ||
51 | + services.put(DeviceProviderRegistry.class, new DeviceProviderRegistryClientProxy(channel)); | ||
52 | + } | ||
53 | + | ||
54 | + | ||
55 | + @Override | ||
56 | + public <T> T get(Class<T> serviceClass) { | ||
57 | + @SuppressWarnings("unchecked") | ||
58 | + T service = (T) services.get(serviceClass); | ||
59 | + if (service != null) { | ||
60 | + return service; | ||
61 | + } | ||
62 | + log.error("{} not supported", serviceClass); | ||
63 | + throw new NoSuchElementException(serviceClass.getTypeName() + " not supported"); | ||
64 | + } | ||
65 | + | ||
66 | + | ||
67 | + @Override | ||
68 | + public String toString() { | ||
69 | + return MoreObjects.toStringHelper(this) | ||
70 | + .add("services", services.keySet()) | ||
71 | + .add("channel", channel.authority()) | ||
72 | + .toString(); | ||
73 | + } | ||
74 | + | ||
75 | +} |
incubator/rpc-grpc/src/main/java/org/onosproject/incubator/rpc/grpc/GrpcRemoteServiceProvider.java
0 → 100644
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 | + | ||
20 | +import java.net.URI; | ||
21 | +import java.util.Map; | ||
22 | +import java.util.Objects; | ||
23 | +import java.util.concurrent.ConcurrentHashMap; | ||
24 | + | ||
25 | +import org.apache.felix.scr.annotations.Activate; | ||
26 | +import org.apache.felix.scr.annotations.Component; | ||
27 | +import org.apache.felix.scr.annotations.Deactivate; | ||
28 | +import org.apache.felix.scr.annotations.Reference; | ||
29 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
30 | +import org.onosproject.incubator.rpc.RemoteServiceContext; | ||
31 | +import org.onosproject.incubator.rpc.RemoteServiceContextProvider; | ||
32 | +import org.onosproject.incubator.rpc.RemoteServiceContextProviderService; | ||
33 | +import org.onosproject.incubator.rpc.RemoteServiceProviderRegistry; | ||
34 | +import org.onosproject.net.provider.ProviderId; | ||
35 | +import org.slf4j.Logger; | ||
36 | +import org.slf4j.LoggerFactory; | ||
37 | + | ||
38 | +import io.grpc.ManagedChannel; | ||
39 | +import io.grpc.netty.NegotiationType; | ||
40 | +import io.grpc.netty.NettyChannelBuilder; | ||
41 | + | ||
42 | + | ||
43 | +// gRPC Client side | ||
44 | +/** | ||
45 | + * RemoteServiceContextProvider based on gRPC. | ||
46 | + */ | ||
47 | +@Component(immediate = true) | ||
48 | +public class GrpcRemoteServiceProvider implements RemoteServiceContextProvider { | ||
49 | + | ||
50 | + public static final String GRPC_SCHEME = "grpc"; | ||
51 | + | ||
52 | + public static final String RPC_PROVIDER_NAME = "org.onosproject.rpc.provider.grpc"; | ||
53 | + | ||
54 | + private static final ProviderId PID = new ProviderId(GRPC_SCHEME, RPC_PROVIDER_NAME); | ||
55 | + | ||
56 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
57 | + | ||
58 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
59 | + protected RemoteServiceProviderRegistry rpcRegistry; | ||
60 | + | ||
61 | + private Map<URI, ManagedChannel> channels = new ConcurrentHashMap<>(); | ||
62 | + | ||
63 | + private RemoteServiceContextProviderService providerService; | ||
64 | + | ||
65 | + | ||
66 | + @Activate | ||
67 | + protected void activate() { | ||
68 | + providerService = rpcRegistry.register(this); | ||
69 | + | ||
70 | + // FIXME remove me. test code to see if gRPC loads in karaf | ||
71 | + //getChannel(URI.create("grpc://localhost:8080")); | ||
72 | + | ||
73 | + log.info("Started"); | ||
74 | + } | ||
75 | + | ||
76 | + @Deactivate | ||
77 | + protected void deactivate() { | ||
78 | + rpcRegistry.unregister(this); | ||
79 | + | ||
80 | + // shutdown all channels | ||
81 | + channels.values().stream() | ||
82 | + .forEach(ManagedChannel::shutdown); | ||
83 | + // Should we wait for shutdown? How? | ||
84 | + channels.clear(); | ||
85 | + log.info("Stopped"); | ||
86 | + } | ||
87 | + | ||
88 | + @Override | ||
89 | + public ProviderId id() { | ||
90 | + return PID; | ||
91 | + } | ||
92 | + | ||
93 | + @Override | ||
94 | + public RemoteServiceContext get(URI uri) { | ||
95 | + // Create gRPC client | ||
96 | + return new GrpcRemoteServiceContext(getChannel(uri)); | ||
97 | + } | ||
98 | + | ||
99 | + private ManagedChannel getChannel(URI uri) { | ||
100 | + checkArgument(Objects.equals(GRPC_SCHEME, uri.getScheme()), | ||
101 | + "Invalid URI scheme: %s", uri.getScheme()); | ||
102 | + | ||
103 | + return channels.compute(uri, (u, ch) -> { | ||
104 | + if (ch != null && !ch.isShutdown()) { | ||
105 | + return ch; | ||
106 | + } else { | ||
107 | + return createChannel(u); | ||
108 | + } | ||
109 | + }); | ||
110 | + } | ||
111 | + | ||
112 | + private ManagedChannel createChannel(URI uri) { | ||
113 | + log.debug("Creating channel for {}", uri); | ||
114 | + return NettyChannelBuilder.forAddress(uri.getHost(), uri.getPort()) | ||
115 | + .negotiationType(NegotiationType.PLAINTEXT) | ||
116 | + .build(); | ||
117 | + } | ||
118 | + | ||
119 | +} |
incubator/rpc-grpc/src/main/java/org/onosproject/incubator/rpc/grpc/GrpcRemoteServiceServer.java
0 → 100644
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 | +import static java.util.stream.Collectors.toList; | ||
20 | +import static org.onosproject.incubator.rpc.grpc.GrpcDeviceUtils.translate; | ||
21 | +import static org.onosproject.net.DeviceId.deviceId; | ||
22 | + | ||
23 | +import java.io.IOException; | ||
24 | +import java.util.Set; | ||
25 | +import java.util.concurrent.CompletableFuture; | ||
26 | +import java.util.concurrent.ExecutionException; | ||
27 | +import java.util.concurrent.TimeUnit; | ||
28 | +import java.util.concurrent.TimeoutException; | ||
29 | +import java.util.concurrent.atomic.AtomicInteger; | ||
30 | + | ||
31 | +import org.apache.felix.scr.annotations.Activate; | ||
32 | +import org.apache.felix.scr.annotations.Component; | ||
33 | +import org.apache.felix.scr.annotations.Deactivate; | ||
34 | +import org.apache.felix.scr.annotations.Modified; | ||
35 | +import org.apache.felix.scr.annotations.Property; | ||
36 | +import org.apache.felix.scr.annotations.Reference; | ||
37 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
38 | +import org.onosproject.grpc.Device.DeviceConnected; | ||
39 | +import org.onosproject.grpc.Device.DeviceDisconnected; | ||
40 | +import org.onosproject.grpc.Device.DeviceProviderMsg; | ||
41 | +import org.onosproject.grpc.Device.DeviceProviderServiceMsg; | ||
42 | +import org.onosproject.grpc.Device.IsReachableResponse; | ||
43 | +import org.onosproject.grpc.Device.PortStatusChanged; | ||
44 | +import org.onosproject.grpc.Device.ReceivedRoleReply; | ||
45 | +import org.onosproject.grpc.Device.RegisterProvider; | ||
46 | +import org.onosproject.grpc.Device.UpdatePortStatistics; | ||
47 | +import org.onosproject.grpc.Device.UpdatePorts; | ||
48 | +import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc; | ||
49 | +import org.onosproject.grpc.DeviceProviderRegistryRpcGrpc.DeviceProviderRegistryRpc; | ||
50 | +import org.onosproject.net.DeviceId; | ||
51 | +import org.onosproject.net.MastershipRole; | ||
52 | +import org.onosproject.net.device.DeviceProvider; | ||
53 | +import org.onosproject.net.device.DeviceProviderRegistry; | ||
54 | +import org.onosproject.net.device.DeviceProviderService; | ||
55 | +import org.onosproject.net.provider.ProviderId; | ||
56 | +import org.osgi.service.component.ComponentContext; | ||
57 | +import org.slf4j.Logger; | ||
58 | +import org.slf4j.LoggerFactory; | ||
59 | + | ||
60 | +import com.google.common.cache.Cache; | ||
61 | +import com.google.common.cache.CacheBuilder; | ||
62 | +import com.google.common.collect.Sets; | ||
63 | + | ||
64 | +import io.grpc.Server; | ||
65 | +import io.grpc.netty.NettyServerBuilder; | ||
66 | +import io.grpc.stub.StreamObserver; | ||
67 | + | ||
68 | +// gRPC Server on Metro-side | ||
69 | +// Translates request received on RPC channel, and calls corresponding Service on | ||
70 | +// Metro-ONOS cluster. | ||
71 | +/** | ||
72 | + * Server side implementation of gRPC based RemoteService. | ||
73 | + */ | ||
74 | +@Component(immediate = true) | ||
75 | +public class GrpcRemoteServiceServer { | ||
76 | + | ||
77 | + private static final String RPC_PROVIDER_NAME = "org.onosproject.rpc.provider.grpc"; | ||
78 | + | ||
79 | + // TODO pick a number | ||
80 | + public static final int DEFAULT_LISTEN_PORT = 11984; | ||
81 | + | ||
82 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
83 | + | ||
84 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
85 | + protected DeviceProviderRegistry deviceProviderRegistry; | ||
86 | + | ||
87 | + | ||
88 | + @Property(name = "listenPort", intValue = DEFAULT_LISTEN_PORT, | ||
89 | + label = "Port to listen on") | ||
90 | + protected int listenPort = DEFAULT_LISTEN_PORT; | ||
91 | + | ||
92 | + private Server server; | ||
93 | + private final Set<DeviceProviderServerProxy> registeredProviders = Sets.newConcurrentHashSet(); | ||
94 | + | ||
95 | + @Activate | ||
96 | + protected void activate(ComponentContext context) throws IOException { | ||
97 | + modified(context); | ||
98 | + | ||
99 | + log.debug("Server starting on {}", listenPort); | ||
100 | + try { | ||
101 | + server = NettyServerBuilder.forPort(listenPort) | ||
102 | + .addService(DeviceProviderRegistryRpcGrpc.bindService(new DeviceProviderRegistryServerProxy())) | ||
103 | + .build().start(); | ||
104 | + } catch (IOException e) { | ||
105 | + log.error("Failed to start gRPC server", e); | ||
106 | + throw e; | ||
107 | + } | ||
108 | + | ||
109 | + log.info("Started on {}", listenPort); | ||
110 | + } | ||
111 | + | ||
112 | + @Deactivate | ||
113 | + protected void deactivate() { | ||
114 | + | ||
115 | + registeredProviders.stream() | ||
116 | + .forEach(deviceProviderRegistry::unregister); | ||
117 | + | ||
118 | + server.shutdown(); | ||
119 | + // Should we wait for shutdown? | ||
120 | + log.info("Stopped"); | ||
121 | + } | ||
122 | + | ||
123 | + @Modified | ||
124 | + public void modified(ComponentContext context) { | ||
125 | + // TODO support dynamic reconfiguration and restarting server? | ||
126 | + } | ||
127 | + | ||
128 | + // RPC Server-side code | ||
129 | + // RPC session Factory | ||
130 | + /** | ||
131 | + * Relays DeviceProviderRegistry calls from RPC client. | ||
132 | + */ | ||
133 | + class DeviceProviderRegistryServerProxy implements DeviceProviderRegistryRpc { | ||
134 | + | ||
135 | + @Override | ||
136 | + public StreamObserver<DeviceProviderServiceMsg> register(StreamObserver<DeviceProviderMsg> toDeviceProvider) { | ||
137 | + log.trace("DeviceProviderRegistryServerProxy#register called!"); | ||
138 | + | ||
139 | + DeviceProviderServerProxy provider = new DeviceProviderServerProxy(toDeviceProvider); | ||
140 | + | ||
141 | + return new DeviceProviderServiceServerProxy(provider, toDeviceProvider); | ||
142 | + } | ||
143 | + } | ||
144 | + | ||
145 | + // Lower -> Upper Controller message | ||
146 | + // RPC Server-side code | ||
147 | + // RPC session handler | ||
148 | + private final class DeviceProviderServiceServerProxy | ||
149 | + implements StreamObserver<DeviceProviderServiceMsg> { | ||
150 | + | ||
151 | + // intentionally shadowing | ||
152 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
153 | + | ||
154 | + private final DeviceProviderServerProxy pairedProvider; | ||
155 | + private final StreamObserver<DeviceProviderMsg> toDeviceProvider; | ||
156 | + | ||
157 | + private final Cache<Integer, CompletableFuture<Boolean>> outstandingIsReachable; | ||
158 | + | ||
159 | + // wrapped providerService | ||
160 | + private DeviceProviderService deviceProviderService; | ||
161 | + | ||
162 | + | ||
163 | + DeviceProviderServiceServerProxy(DeviceProviderServerProxy provider, | ||
164 | + StreamObserver<DeviceProviderMsg> toDeviceProvider) { | ||
165 | + this.pairedProvider = provider; | ||
166 | + this.toDeviceProvider = toDeviceProvider; | ||
167 | + outstandingIsReachable = CacheBuilder.newBuilder() | ||
168 | + .expireAfterWrite(1, TimeUnit.MINUTES) | ||
169 | + .build(); | ||
170 | + | ||
171 | + // pair RPC session in other direction | ||
172 | + provider.pair(this); | ||
173 | + } | ||
174 | + | ||
175 | + @Override | ||
176 | + public void onNext(DeviceProviderServiceMsg msg) { | ||
177 | + try { | ||
178 | + log.trace("DeviceProviderServiceServerProxy received: {}", msg); | ||
179 | + onMethod(msg); | ||
180 | + } catch (Exception e) { | ||
181 | + log.error("Exception thrown handling {}", msg, e); | ||
182 | + onError(e); | ||
183 | + throw e; | ||
184 | + } | ||
185 | + } | ||
186 | + | ||
187 | + /** | ||
188 | + * Translates received RPC message to {@link DeviceProviderService} method calls. | ||
189 | + * @param msg DeviceProviderService message | ||
190 | + */ | ||
191 | + private void onMethod(DeviceProviderServiceMsg msg) { | ||
192 | + switch (msg.getMethodCase()) { | ||
193 | + case REGISTER_PROVIDER: | ||
194 | + RegisterProvider registerProvider = msg.getRegisterProvider(); | ||
195 | + // TODO Do we care about provider name? | ||
196 | + pairedProvider.setProviderId(new ProviderId(registerProvider.getProviderScheme(), RPC_PROVIDER_NAME)); | ||
197 | + registeredProviders.add(pairedProvider); | ||
198 | + deviceProviderService = deviceProviderRegistry.register(pairedProvider); | ||
199 | + break; | ||
200 | + | ||
201 | + case DEVICE_CONNECTED: | ||
202 | + DeviceConnected deviceConnected = msg.getDeviceConnected(); | ||
203 | + deviceProviderService.deviceConnected(deviceId(deviceConnected.getDeviceId()), | ||
204 | + translate(deviceConnected.getDeviceDescription())); | ||
205 | + break; | ||
206 | + case DEVICE_DISCONNECTED: | ||
207 | + DeviceDisconnected deviceDisconnected = msg.getDeviceDisconnected(); | ||
208 | + deviceProviderService.deviceDisconnected(deviceId(deviceDisconnected.getDeviceId())); | ||
209 | + break; | ||
210 | + case UPDATE_PORTS: | ||
211 | + UpdatePorts updatePorts = msg.getUpdatePorts(); | ||
212 | + deviceProviderService.updatePorts(deviceId(updatePorts.getDeviceId()), | ||
213 | + updatePorts.getPortDescriptionsList() | ||
214 | + .stream() | ||
215 | + .map(GrpcDeviceUtils::translate) | ||
216 | + .collect(toList())); | ||
217 | + break; | ||
218 | + case PORT_STATUS_CHANGED: | ||
219 | + PortStatusChanged portStatusChanged = msg.getPortStatusChanged(); | ||
220 | + deviceProviderService.portStatusChanged(deviceId(portStatusChanged.getDeviceId()), | ||
221 | + translate(portStatusChanged.getPortDescription())); | ||
222 | + break; | ||
223 | + case RECEIVED_ROLE_REPLY: | ||
224 | + ReceivedRoleReply receivedRoleReply = msg.getReceivedRoleReply(); | ||
225 | + deviceProviderService.receivedRoleReply(deviceId(receivedRoleReply.getDeviceId()), | ||
226 | + translate(receivedRoleReply.getRequested()), | ||
227 | + translate(receivedRoleReply.getResponse())); | ||
228 | + break; | ||
229 | + case UPDATE_PORT_STATISTICS: | ||
230 | + UpdatePortStatistics updatePortStatistics = msg.getUpdatePortStatistics(); | ||
231 | + deviceProviderService.updatePortStatistics(deviceId(updatePortStatistics.getDeviceId()), | ||
232 | + updatePortStatistics.getPortStatisticsList() | ||
233 | + .stream() | ||
234 | + .map(GrpcDeviceUtils::translate) | ||
235 | + .collect(toList())); | ||
236 | + break; | ||
237 | + | ||
238 | + // return value of DeviceProvider#isReachable | ||
239 | + case IS_REACHABLE_RESPONSE: | ||
240 | + IsReachableResponse isReachableResponse = msg.getIsReachableResponse(); | ||
241 | + int xid = isReachableResponse.getXid(); | ||
242 | + boolean isReachable = isReachableResponse.getIsReachable(); | ||
243 | + CompletableFuture<Boolean> result = outstandingIsReachable.asMap().remove(xid); | ||
244 | + if (result != null) { | ||
245 | + result.complete(isReachable); | ||
246 | + } | ||
247 | + break; | ||
248 | + | ||
249 | + case METHOD_NOT_SET: | ||
250 | + default: | ||
251 | + log.warn("Unexpected message received {}", msg); | ||
252 | + break; | ||
253 | + } | ||
254 | + } | ||
255 | + | ||
256 | + @Override | ||
257 | + public void onCompleted() { | ||
258 | + log.info("DeviceProviderServiceServerProxy completed"); | ||
259 | + deviceProviderRegistry.unregister(pairedProvider); | ||
260 | + registeredProviders.remove(pairedProvider); | ||
261 | + toDeviceProvider.onCompleted(); | ||
262 | + } | ||
263 | + | ||
264 | + @Override | ||
265 | + public void onError(Throwable e) { | ||
266 | + log.error("DeviceProviderServiceServerProxy#onError", e); | ||
267 | + deviceProviderRegistry.unregister(pairedProvider); | ||
268 | + registeredProviders.remove(pairedProvider); | ||
269 | + // TODO What is the proper clean up for bi-di stream on error? | ||
270 | + // sample suggests no-op | ||
271 | + toDeviceProvider.onError(e); | ||
272 | + } | ||
273 | + | ||
274 | + | ||
275 | + /** | ||
276 | + * Registers Future for {@link DeviceProvider#isReachable(DeviceId)} return value. | ||
277 | + * @param xid IsReachable call ID. | ||
278 | + * @param reply Future to | ||
279 | + */ | ||
280 | + void register(int xid, CompletableFuture<Boolean> reply) { | ||
281 | + outstandingIsReachable.put(xid, reply); | ||
282 | + } | ||
283 | + | ||
284 | + } | ||
285 | + | ||
286 | + // Upper -> Lower Controller message | ||
287 | + /** | ||
288 | + * Relay DeviceProvider calls to RPC client. | ||
289 | + */ | ||
290 | + private final class DeviceProviderServerProxy | ||
291 | + implements DeviceProvider { | ||
292 | + | ||
293 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
294 | + | ||
295 | + // xid for isReachable calls | ||
296 | + private final AtomicInteger xidPool = new AtomicInteger(); | ||
297 | + private final StreamObserver<DeviceProviderMsg> toDeviceProvider; | ||
298 | + | ||
299 | + private DeviceProviderServiceServerProxy deviceProviderServiceProxy = null; | ||
300 | + private ProviderId providerId; | ||
301 | + | ||
302 | + DeviceProviderServerProxy(StreamObserver<DeviceProviderMsg> toDeviceProvider) { | ||
303 | + this.toDeviceProvider = toDeviceProvider; | ||
304 | + } | ||
305 | + | ||
306 | + void setProviderId(ProviderId pid) { | ||
307 | + this.providerId = pid; | ||
308 | + } | ||
309 | + | ||
310 | + /** | ||
311 | + * Registers RPC stream in other direction. | ||
312 | + * @param deviceProviderServiceProxy {@link DeviceProviderServiceServerProxy} | ||
313 | + */ | ||
314 | + void pair(DeviceProviderServiceServerProxy deviceProviderServiceProxy) { | ||
315 | + this.deviceProviderServiceProxy = deviceProviderServiceProxy; | ||
316 | + } | ||
317 | + | ||
318 | + @Override | ||
319 | + public void triggerProbe(DeviceId deviceId) { | ||
320 | + log.trace("triggerProbe({})", deviceId); | ||
321 | + DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder(); | ||
322 | + msgBuilder.setTriggerProbe(msgBuilder.getTriggerProbeBuilder() | ||
323 | + .setDeviceId(deviceId.toString()) | ||
324 | + .build()); | ||
325 | + DeviceProviderMsg triggerProbeMsg = msgBuilder.build(); | ||
326 | + toDeviceProvider.onNext(triggerProbeMsg); | ||
327 | + // TODO Catch Exceptions and call onError() | ||
328 | + } | ||
329 | + | ||
330 | + @Override | ||
331 | + public void roleChanged(DeviceId deviceId, MastershipRole newRole) { | ||
332 | + log.trace("roleChanged({}, {})", deviceId, newRole); | ||
333 | + DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder(); | ||
334 | + msgBuilder.setRoleChanged(msgBuilder.getRoleChangedBuilder() | ||
335 | + .setDeviceId(deviceId.toString()) | ||
336 | + .setNewRole(translate(newRole)) | ||
337 | + .build()); | ||
338 | + toDeviceProvider.onNext(msgBuilder.build()); | ||
339 | + // TODO Catch Exceptions and call onError() | ||
340 | + } | ||
341 | + | ||
342 | + @Override | ||
343 | + public boolean isReachable(DeviceId deviceId) { | ||
344 | + log.trace("isReachable({})", deviceId); | ||
345 | + CompletableFuture<Boolean> result = new CompletableFuture<>(); | ||
346 | + final int xid = xidPool.incrementAndGet(); | ||
347 | + | ||
348 | + DeviceProviderMsg.Builder msgBuilder = DeviceProviderMsg.newBuilder(); | ||
349 | + msgBuilder.setIsReachableRequest(msgBuilder.getIsReachableRequestBuilder() | ||
350 | + .setXid(xid) | ||
351 | + .setDeviceId(deviceId.toString()) | ||
352 | + .build()); | ||
353 | + | ||
354 | + // Associate xid and register above future some where | ||
355 | + // in DeviceProviderService channel to receive reply | ||
356 | + if (deviceProviderServiceProxy != null) { | ||
357 | + deviceProviderServiceProxy.register(xid, result); | ||
358 | + } | ||
359 | + | ||
360 | + // send message down RPC | ||
361 | + toDeviceProvider.onNext(msgBuilder.build()); | ||
362 | + | ||
363 | + // wait for reply | ||
364 | + try { | ||
365 | + return result.get(10, TimeUnit.SECONDS); | ||
366 | + } catch (InterruptedException e) { | ||
367 | + log.debug("isReachable({}) was Interrupted", deviceId, e); | ||
368 | + Thread.currentThread().interrupt(); | ||
369 | + } catch (TimeoutException e) { | ||
370 | + log.warn("isReachable({}) Timed out", deviceId, e); | ||
371 | + } catch (ExecutionException e) { | ||
372 | + log.error("isReachable({}) Execution failed", deviceId, e); | ||
373 | + // close session? | ||
374 | + } | ||
375 | + return false; | ||
376 | + // TODO Catch Exceptions and call onError() | ||
377 | + } | ||
378 | + | ||
379 | + @Override | ||
380 | + public ProviderId id() { | ||
381 | + return checkNotNull(providerId, "not initialized yet"); | ||
382 | + } | ||
383 | + | ||
384 | + } | ||
385 | +} |
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 | + | ||
17 | +/** | ||
18 | + * gRPC based RemoteServiceProvider implementation. | ||
19 | + */ | ||
20 | +package org.onosproject.incubator.rpc.grpc; |
1 | +syntax = "proto3"; | ||
2 | +option java_package = "org.onosproject.grpc"; | ||
3 | + | ||
4 | +import "Port.proto"; | ||
5 | +package Device; | ||
6 | + | ||
7 | +enum DeviceType { | ||
8 | + OTHER = 0; | ||
9 | + SWITCH = 1; | ||
10 | + ROUTER = 2; | ||
11 | + ROADM = 3; | ||
12 | + OTN = 4; | ||
13 | + ROADM_OTN = 5; | ||
14 | + FIREWALL = 6; | ||
15 | + BALANCER = 7; | ||
16 | + IPS = 8; | ||
17 | + IDS = 9; | ||
18 | + CONTROLLER = 10; | ||
19 | + VIRTUAL = 11; | ||
20 | + FIBER_SWITCH = 12; | ||
21 | + MICROWAVE = 13; | ||
22 | +} | ||
23 | + | ||
24 | +message DeviceDescription { | ||
25 | + string device_Uri = 1; | ||
26 | + DeviceType type = 2; | ||
27 | + string manufacturer = 3; | ||
28 | + string hw_version = 4; | ||
29 | + string sw_version = 5; | ||
30 | + string serial_number = 6; | ||
31 | + string chassis_id = 7; | ||
32 | + map<string, string> annotations = 8; | ||
33 | +} | ||
34 | + | ||
35 | +enum MastershipRole { | ||
36 | + NONE = 0; | ||
37 | + MASTER = 1; | ||
38 | + STANDBY = 2; | ||
39 | +} | ||
40 | + | ||
41 | +message DeviceConnected { | ||
42 | + // DeviceID as String DeviceId#toString | ||
43 | + string device_id = 1; | ||
44 | + DeviceDescription device_description = 2; | ||
45 | +} | ||
46 | + | ||
47 | +message DeviceDisconnected { | ||
48 | + // DeviceID as String DeviceId#toString | ||
49 | + string device_id = 1; | ||
50 | +} | ||
51 | + | ||
52 | +message UpdatePorts { | ||
53 | + // DeviceID as String DeviceId#toString | ||
54 | + string device_id = 1; | ||
55 | + repeated Port.PortDescription port_descriptions= 2; | ||
56 | +} | ||
57 | + | ||
58 | +message PortStatusChanged { | ||
59 | + // DeviceID as String DeviceId#toString | ||
60 | + string device_id = 1; | ||
61 | + Port.PortDescription port_description= 2; | ||
62 | +} | ||
63 | + | ||
64 | +message ReceivedRoleReply { | ||
65 | + // DeviceID as String DeviceId#toString | ||
66 | + string device_id = 1; | ||
67 | + MastershipRole requested = 2; | ||
68 | + MastershipRole response = 3; | ||
69 | +} | ||
70 | + | ||
71 | +message UpdatePortStatistics { | ||
72 | + // DeviceID as String DeviceId#toString | ||
73 | + string device_id = 1; | ||
74 | + repeated Port.PortStatistics port_statistics = 2; | ||
75 | +} | ||
76 | + | ||
77 | +message RegisterProvider { | ||
78 | + // DeviceProvider's ProviderId scheme | ||
79 | + string provider_scheme = 1; | ||
80 | +} | ||
81 | + | ||
82 | +message DeviceProviderServiceMsg { | ||
83 | + oneof method { | ||
84 | + DeviceConnected device_connected= 1; | ||
85 | + DeviceDisconnected device_disconnected = 2; | ||
86 | + UpdatePorts update_ports= 3; | ||
87 | + PortStatusChanged port_status_changed = 4; | ||
88 | + ReceivedRoleReply received_role_reply = 5; | ||
89 | + UpdatePortStatistics update_port_statistics = 6; | ||
90 | + | ||
91 | + // This message is for return value of DeviceProvider#isReachable | ||
92 | + IsReachableResponse is_reachable_response = 7; | ||
93 | + | ||
94 | + // This MUST be the 1st message over the stream | ||
95 | + RegisterProvider register_provider = 8; | ||
96 | + } | ||
97 | +} | ||
98 | + | ||
99 | +message TriggerProbe { | ||
100 | + // DeviceID as String DeviceId#toString | ||
101 | + string device_id = 1; | ||
102 | +} | ||
103 | + | ||
104 | +message RoleChanged { | ||
105 | + // DeviceID as String DeviceId#toString | ||
106 | + string device_id = 1; | ||
107 | + MastershipRole new_role = 2; | ||
108 | +} | ||
109 | + | ||
110 | +message IsReachableRequest { | ||
111 | + int32 xid = 1; | ||
112 | + // DeviceID as String DeviceId#toString | ||
113 | + string device_id = 2; | ||
114 | +} | ||
115 | + | ||
116 | +message IsReachableResponse { | ||
117 | + int32 xid = 1; | ||
118 | + bool is_reachable = 2; | ||
119 | +} | ||
120 | + | ||
121 | +message DeviceProviderMsg { | ||
122 | + oneof method { | ||
123 | + TriggerProbe trigger_probe = 1; | ||
124 | + RoleChanged role_changed = 2; | ||
125 | + IsReachableRequest is_reachable_request= 3; | ||
126 | + } | ||
127 | +} | ||
128 | + | ||
129 | +service DeviceProviderRegistryRpc { | ||
130 | + rpc Register(stream DeviceProviderServiceMsg) returns (stream DeviceProviderMsg); | ||
131 | +} |
incubator/rpc-grpc/src/main/proto/Port.proto
0 → 100644
1 | +syntax = "proto3"; | ||
2 | +option java_package = "org.onosproject.grpc"; | ||
3 | + | ||
4 | +package Port; | ||
5 | + | ||
6 | +enum PortType { | ||
7 | + // Signifies copper-based connectivity. | ||
8 | + COPPER = 0; | ||
9 | + // Signifies optical fiber-based connectivity. | ||
10 | + FIBER = 1; | ||
11 | + // Signifies optical fiber-based packet port. | ||
12 | + PACKET = 2; | ||
13 | + // Signifies optical fiber-based optical tributary port (called T-port). | ||
14 | + //The signal from the client side will be formed into a ITU G.709 (OTN) frame. | ||
15 | + ODUCLT = 3; | ||
16 | + // Signifies optical fiber-based Line-side port (called L-port). | ||
17 | + OCH = 4; | ||
18 | + // Signifies optical fiber-based WDM port (called W-port). | ||
19 | + //Optical Multiplexing Section (See ITU G.709). | ||
20 | + OMS = 5; | ||
21 | + // Signifies virtual port. | ||
22 | + VIRTUAL = 6; | ||
23 | +} | ||
24 | + | ||
25 | +// TODO What are we going to do with more specific PortDescription ... | ||
26 | +message PortDescription { | ||
27 | + // PortNumber as String PortNumber#toString | ||
28 | + string port_number = 1; | ||
29 | + bool is_enabled = 2; | ||
30 | + PortType type = 3; | ||
31 | + int64 port_speed = 4; | ||
32 | + map<string, string> annotations = 8; | ||
33 | +} | ||
34 | + | ||
35 | +message PortStatistics { | ||
36 | + int32 port = 1; | ||
37 | + int64 packets_received = 2; | ||
38 | + int64 packets_sent = 3; | ||
39 | + // TODO add all other fields | ||
40 | +} |
incubator/rpc-grpc/src/test/java/org/onosproject/incubator/rpc/grpc/GrpcRemoteServiceTest.java
0 → 100644
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.junit.Assert.*; | ||
19 | +import static org.onosproject.net.DeviceId.deviceId; | ||
20 | + | ||
21 | +import java.io.IOException; | ||
22 | +import java.net.ServerSocket; | ||
23 | +import java.net.URI; | ||
24 | +import java.util.Collection; | ||
25 | +import java.util.Collections; | ||
26 | +import java.util.List; | ||
27 | +import java.util.Set; | ||
28 | +import java.util.concurrent.CountDownLatch; | ||
29 | +import java.util.concurrent.TimeUnit; | ||
30 | + | ||
31 | +import org.apache.commons.lang3.RandomUtils; | ||
32 | +import org.junit.After; | ||
33 | +import org.junit.Before; | ||
34 | +import org.junit.Test; | ||
35 | +import org.onlab.packet.ChassisId; | ||
36 | +import org.onosproject.incubator.rpc.RemoteServiceContext; | ||
37 | +import org.onosproject.incubator.rpc.RemoteServiceContextProvider; | ||
38 | +import org.onosproject.incubator.rpc.RemoteServiceContextProviderService; | ||
39 | +import org.onosproject.incubator.rpc.RemoteServiceProviderRegistry; | ||
40 | +import org.onosproject.net.DefaultAnnotations; | ||
41 | +import org.onosproject.net.Device.Type; | ||
42 | +import org.onosproject.net.DeviceId; | ||
43 | +import org.onosproject.net.MastershipRole; | ||
44 | +import org.onosproject.net.PortNumber; | ||
45 | +import org.onosproject.net.SparseAnnotations; | ||
46 | +import org.onosproject.net.device.DefaultDeviceDescription; | ||
47 | +import org.onosproject.net.device.DefaultPortDescription; | ||
48 | +import org.onosproject.net.device.DeviceDescription; | ||
49 | +import org.onosproject.net.device.DeviceProvider; | ||
50 | +import org.onosproject.net.device.DeviceProviderRegistry; | ||
51 | +import org.onosproject.net.device.DeviceProviderService; | ||
52 | +import org.onosproject.net.device.PortDescription; | ||
53 | +import org.onosproject.net.device.PortStatistics; | ||
54 | +import org.onosproject.net.provider.AbstractProviderRegistry; | ||
55 | +import org.onosproject.net.provider.AbstractProviderService; | ||
56 | +import org.onosproject.net.provider.ProviderId; | ||
57 | +import org.slf4j.Logger; | ||
58 | +import org.slf4j.LoggerFactory; | ||
59 | + | ||
60 | +import com.google.common.collect.ImmutableList; | ||
61 | + | ||
62 | +/** | ||
63 | + * Set of tests of the gRPC RemoteService components. | ||
64 | + */ | ||
65 | +public class GrpcRemoteServiceTest { | ||
66 | + | ||
67 | + private static final DeviceId DEVICE_ID = deviceId("dev:000001"); | ||
68 | + | ||
69 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
70 | + | ||
71 | + private static final ProviderId PID = new ProviderId("test", "com.exmaple.test"); | ||
72 | + | ||
73 | + private static final URI DURI = URI.create("dev:000001"); | ||
74 | + | ||
75 | + private static final String MFR = "mfr"; | ||
76 | + | ||
77 | + private static final String HW = "hw"; | ||
78 | + | ||
79 | + private static final String SW = "sw"; | ||
80 | + | ||
81 | + private static final String SN = "serial"; | ||
82 | + | ||
83 | + private static final ChassisId CHASSIS = new ChassisId(42); | ||
84 | + | ||
85 | + private static final SparseAnnotations ANON = DefaultAnnotations.builder() | ||
86 | + .set("foo", "var") | ||
87 | + .build(); | ||
88 | + | ||
89 | + private static final PortNumber PORT = PortNumber.portNumber(99); | ||
90 | + | ||
91 | + private static final DeviceDescription DDESC | ||
92 | + = new DefaultDeviceDescription(DURI, Type.SWITCH, MFR, HW, SW, SN, | ||
93 | + CHASSIS, ANON); | ||
94 | + | ||
95 | + private GrpcRemoteServiceServer server; | ||
96 | + private GrpcRemoteServiceProvider client; | ||
97 | + | ||
98 | + private DeviceProvider svSideDeviceProvider; | ||
99 | + | ||
100 | + private MTestDeviceProviderService svDeviceProviderService; | ||
101 | + | ||
102 | + private CountDownLatch serverReady; | ||
103 | + | ||
104 | + private URI uri; | ||
105 | + | ||
106 | + public static int pickListenPort() { | ||
107 | + try { | ||
108 | + // pick unused port | ||
109 | + ServerSocket socket = new ServerSocket(0); | ||
110 | + int port = socket.getLocalPort(); | ||
111 | + socket.close(); | ||
112 | + return port; | ||
113 | + } catch (IOException e) { | ||
114 | + // something went wrong, try picking randomly | ||
115 | + return RandomUtils.nextInt(49152, 0xFFFF + 1); | ||
116 | + } | ||
117 | + } | ||
118 | + | ||
119 | + @Before | ||
120 | + public void setUp() throws Exception { | ||
121 | + serverReady = new CountDownLatch(1); | ||
122 | + server = new GrpcRemoteServiceServer(); | ||
123 | + server.deviceProviderRegistry = new MTestDeviceProviderRegistry(); | ||
124 | + // todo: pass proper ComponentContext | ||
125 | + server.listenPort = pickListenPort(); | ||
126 | + uri = URI.create("grpc://localhost:" + server.listenPort); | ||
127 | + server.activate(null); | ||
128 | + | ||
129 | + client = new GrpcRemoteServiceProvider(); | ||
130 | + client.rpcRegistry = new NoOpRemoteServiceProviderRegistry(); | ||
131 | + client.activate(); | ||
132 | + } | ||
133 | + | ||
134 | + @After | ||
135 | + public void tearDown() { | ||
136 | + client.deactivate(); | ||
137 | + server.deactivate(); | ||
138 | + } | ||
139 | + | ||
140 | + private static void assertEqualsButNotSame(Object expected, Object actual) { | ||
141 | + assertEquals(expected, actual); | ||
142 | + assertNotSame("Cannot be same instance if it properly went through gRPC", | ||
143 | + expected, actual); | ||
144 | + } | ||
145 | + | ||
146 | + @Test | ||
147 | + public void basics() throws InterruptedException { | ||
148 | + RemoteServiceContext remoteServiceContext = client.get(uri); | ||
149 | + assertNotNull(remoteServiceContext); | ||
150 | + | ||
151 | + DeviceProviderRegistry deviceProviderRegistry = remoteServiceContext.get(DeviceProviderRegistry.class); | ||
152 | + assertNotNull(deviceProviderRegistry); | ||
153 | + | ||
154 | + CTestDeviceProvider clDeviceProvider = new CTestDeviceProvider(); | ||
155 | + DeviceProviderService clDeviceProviderService = deviceProviderRegistry.register(clDeviceProvider); | ||
156 | + | ||
157 | + assertTrue(serverReady.await(10, TimeUnit.SECONDS)); | ||
158 | + | ||
159 | + // client to server communication | ||
160 | + clDeviceProviderService.deviceConnected(DEVICE_ID, DDESC); | ||
161 | + assertTrue(svDeviceProviderService.deviceConnected.await(10, TimeUnit.SECONDS)); | ||
162 | + assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.deviceConnectedDid); | ||
163 | + assertEqualsButNotSame(DDESC, svDeviceProviderService.deviceConnectedDesc); | ||
164 | + | ||
165 | + PortDescription portDescription = new DefaultPortDescription(PORT, true, ANON); | ||
166 | + List<PortDescription> portDescriptions = ImmutableList.of(portDescription); | ||
167 | + clDeviceProviderService.updatePorts(DEVICE_ID, portDescriptions); | ||
168 | + assertTrue(svDeviceProviderService.updatePorts.await(10, TimeUnit.SECONDS)); | ||
169 | + assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.updatePortsDid); | ||
170 | + assertEqualsButNotSame(portDescriptions, svDeviceProviderService.updatePortsDescs); | ||
171 | + | ||
172 | + MastershipRole cRole = MastershipRole.MASTER; | ||
173 | + MastershipRole dRole = MastershipRole.STANDBY; | ||
174 | + clDeviceProviderService.receivedRoleReply(DEVICE_ID, cRole, dRole); | ||
175 | + assertTrue(svDeviceProviderService.receivedRoleReply.await(10, TimeUnit.SECONDS)); | ||
176 | + assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.receivedRoleReplyDid); | ||
177 | + assertEquals(cRole, svDeviceProviderService.receivedRoleReplyRequested); | ||
178 | + assertEquals(dRole, svDeviceProviderService.receivedRoleReplyResponse); | ||
179 | + | ||
180 | + clDeviceProviderService.portStatusChanged(DEVICE_ID, portDescription); | ||
181 | + assertTrue(svDeviceProviderService.portStatusChanged.await(10, TimeUnit.SECONDS)); | ||
182 | + assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.portStatusChangedDid); | ||
183 | + assertEqualsButNotSame(portDescription, svDeviceProviderService.portStatusChangedDesc); | ||
184 | + | ||
185 | + Collection<PortStatistics> portStatistics = Collections.emptyList(); | ||
186 | + clDeviceProviderService.updatePortStatistics(DEVICE_ID, portStatistics); | ||
187 | + assertTrue(svDeviceProviderService.updatePortStatistics.await(10, TimeUnit.SECONDS)); | ||
188 | + assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.updatePortStatisticsDid); | ||
189 | + assertEqualsButNotSame(portStatistics, svDeviceProviderService.updatePortStatisticsStats); | ||
190 | + | ||
191 | + clDeviceProviderService.deviceDisconnected(DEVICE_ID); | ||
192 | + assertTrue(svDeviceProviderService.deviceDisconnected.await(10, TimeUnit.SECONDS)); | ||
193 | + assertEqualsButNotSame(DEVICE_ID, svDeviceProviderService.deviceDisconnectedDid); | ||
194 | + | ||
195 | + | ||
196 | + | ||
197 | + // server to client communication | ||
198 | + svSideDeviceProvider.triggerProbe(DEVICE_ID); | ||
199 | + assertTrue(clDeviceProvider.triggerProbe.await(10, TimeUnit.SECONDS)); | ||
200 | + assertEquals(DEVICE_ID, clDeviceProvider.triggerProbeDid); | ||
201 | + assertNotSame("Cannot be same instance if it properly went through gRPC", | ||
202 | + DEVICE_ID, clDeviceProvider.triggerProbeDid); | ||
203 | + | ||
204 | + svSideDeviceProvider.roleChanged(DEVICE_ID, MastershipRole.STANDBY); | ||
205 | + assertTrue(clDeviceProvider.roleChanged.await(10, TimeUnit.SECONDS)); | ||
206 | + assertEquals(DEVICE_ID, clDeviceProvider.roleChangedDid); | ||
207 | + assertNotSame("Cannot be same instance if it properly went through gRPC", | ||
208 | + DEVICE_ID, clDeviceProvider.roleChangedDid); | ||
209 | + assertEquals(MastershipRole.STANDBY, clDeviceProvider.roleChangedNewRole); | ||
210 | + | ||
211 | + clDeviceProvider.isReachableReply = false; | ||
212 | + assertEquals(clDeviceProvider.isReachableReply, | ||
213 | + svSideDeviceProvider.isReachable(DEVICE_ID)); | ||
214 | + assertTrue(clDeviceProvider.isReachable.await(10, TimeUnit.SECONDS)); | ||
215 | + assertEquals(DEVICE_ID, clDeviceProvider.isReachableDid); | ||
216 | + assertNotSame("Cannot be same instance if it properly went through gRPC", | ||
217 | + DEVICE_ID, clDeviceProvider.isReachableDid); | ||
218 | + } | ||
219 | + | ||
220 | + /** | ||
221 | + * Device Provider on CO side. | ||
222 | + */ | ||
223 | + public class CTestDeviceProvider implements DeviceProvider { | ||
224 | + | ||
225 | + final CountDownLatch triggerProbe = new CountDownLatch(1); | ||
226 | + DeviceId triggerProbeDid; | ||
227 | + | ||
228 | + final CountDownLatch roleChanged = new CountDownLatch(1); | ||
229 | + DeviceId roleChangedDid; | ||
230 | + MastershipRole roleChangedNewRole; | ||
231 | + | ||
232 | + final CountDownLatch isReachable = new CountDownLatch(1); | ||
233 | + DeviceId isReachableDid; | ||
234 | + boolean isReachableReply = false; | ||
235 | + | ||
236 | + @Override | ||
237 | + public ProviderId id() { | ||
238 | + return PID; | ||
239 | + } | ||
240 | + | ||
241 | + @Override | ||
242 | + public void triggerProbe(DeviceId deviceId) { | ||
243 | + log.info("triggerProbe({}) on Client called", deviceId); | ||
244 | + triggerProbeDid = deviceId; | ||
245 | + triggerProbe.countDown(); | ||
246 | + } | ||
247 | + | ||
248 | + @Override | ||
249 | + public void roleChanged(DeviceId deviceId, MastershipRole newRole) { | ||
250 | + log.info("roleChanged({},{}) on Client called", deviceId, newRole); | ||
251 | + roleChangedDid = deviceId; | ||
252 | + roleChangedNewRole = newRole; | ||
253 | + roleChanged.countDown(); | ||
254 | + } | ||
255 | + | ||
256 | + @Override | ||
257 | + public boolean isReachable(DeviceId deviceId) { | ||
258 | + log.info("isReachable({}) on Client called", deviceId); | ||
259 | + isReachableDid = deviceId; | ||
260 | + isReachable.countDown(); | ||
261 | + return isReachableReply; | ||
262 | + } | ||
263 | + | ||
264 | + } | ||
265 | + | ||
266 | + class NoOpRemoteServiceProviderRegistry | ||
267 | + implements RemoteServiceProviderRegistry { | ||
268 | + | ||
269 | + @Override | ||
270 | + public RemoteServiceContextProviderService register(RemoteServiceContextProvider provider) { | ||
271 | + return new RemoteServiceContextProviderService() { | ||
272 | + | ||
273 | + @Override | ||
274 | + public RemoteServiceContextProvider provider() { | ||
275 | + return provider; | ||
276 | + } | ||
277 | + }; | ||
278 | + } | ||
279 | + | ||
280 | + @Override | ||
281 | + public void unregister(RemoteServiceContextProvider provider) { | ||
282 | + } | ||
283 | + | ||
284 | + @Override | ||
285 | + public Set<ProviderId> getProviders() { | ||
286 | + return Collections.emptySet(); | ||
287 | + } | ||
288 | + } | ||
289 | + | ||
290 | + /** | ||
291 | + * DeviceProvider on Metro side. | ||
292 | + */ | ||
293 | + public class MTestDeviceProviderRegistry | ||
294 | + extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService> | ||
295 | + implements DeviceProviderRegistry { | ||
296 | + | ||
297 | + @Override | ||
298 | + protected DeviceProviderService createProviderService(DeviceProvider provider) { | ||
299 | + log.info("createProviderService({})", provider); | ||
300 | + svSideDeviceProvider = provider; | ||
301 | + svDeviceProviderService = new MTestDeviceProviderService(provider); | ||
302 | + serverReady.countDown(); | ||
303 | + return svDeviceProviderService; | ||
304 | + } | ||
305 | + | ||
306 | + } | ||
307 | + | ||
308 | + private final class MTestDeviceProviderService | ||
309 | + extends AbstractProviderService<DeviceProvider> | ||
310 | + implements DeviceProviderService { | ||
311 | + | ||
312 | + public MTestDeviceProviderService(DeviceProvider provider) { | ||
313 | + super(provider); | ||
314 | + } | ||
315 | + | ||
316 | + | ||
317 | + final CountDownLatch deviceConnected = new CountDownLatch(1); | ||
318 | + DeviceId deviceConnectedDid; | ||
319 | + DeviceDescription deviceConnectedDesc; | ||
320 | + | ||
321 | + @Override | ||
322 | + public void deviceConnected(DeviceId deviceId, | ||
323 | + DeviceDescription deviceDescription) { | ||
324 | + log.info("deviceConnected({}, {}) on Server called", deviceId, deviceDescription); | ||
325 | + deviceConnectedDid = deviceId; | ||
326 | + deviceConnectedDesc = deviceDescription; | ||
327 | + deviceConnected.countDown(); | ||
328 | + } | ||
329 | + | ||
330 | + | ||
331 | + final CountDownLatch updatePorts = new CountDownLatch(1); | ||
332 | + DeviceId updatePortsDid; | ||
333 | + List<PortDescription> updatePortsDescs; | ||
334 | + | ||
335 | + @Override | ||
336 | + public void updatePorts(DeviceId deviceId, | ||
337 | + List<PortDescription> portDescriptions) { | ||
338 | + log.info("updatePorts({}, {}) on Server called", deviceId, portDescriptions); | ||
339 | + updatePortsDid = deviceId; | ||
340 | + updatePortsDescs = portDescriptions; | ||
341 | + updatePorts.countDown(); | ||
342 | + } | ||
343 | + | ||
344 | + final CountDownLatch receivedRoleReply = new CountDownLatch(1); | ||
345 | + DeviceId receivedRoleReplyDid; | ||
346 | + MastershipRole receivedRoleReplyRequested; | ||
347 | + MastershipRole receivedRoleReplyResponse; | ||
348 | + | ||
349 | + @Override | ||
350 | + public void receivedRoleReply(DeviceId deviceId, MastershipRole requested, | ||
351 | + MastershipRole response) { | ||
352 | + log.info("receivedRoleReply({}, {}, {}) on Server called", deviceId, requested, response); | ||
353 | + receivedRoleReplyDid = deviceId; | ||
354 | + receivedRoleReplyRequested = requested; | ||
355 | + receivedRoleReplyResponse = response; | ||
356 | + receivedRoleReply.countDown(); | ||
357 | + } | ||
358 | + | ||
359 | + final CountDownLatch portStatusChanged = new CountDownLatch(1); | ||
360 | + DeviceId portStatusChangedDid; | ||
361 | + PortDescription portStatusChangedDesc; | ||
362 | + | ||
363 | + | ||
364 | + @Override | ||
365 | + public void portStatusChanged(DeviceId deviceId, | ||
366 | + PortDescription portDescription) { | ||
367 | + log.info("portStatusChanged({}, {}) on Server called", deviceId, portDescription); | ||
368 | + portStatusChangedDid = deviceId; | ||
369 | + portStatusChangedDesc = portDescription; | ||
370 | + portStatusChanged.countDown(); | ||
371 | + } | ||
372 | + | ||
373 | + final CountDownLatch updatePortStatistics = new CountDownLatch(1); | ||
374 | + DeviceId updatePortStatisticsDid; | ||
375 | + Collection<PortStatistics> updatePortStatisticsStats; | ||
376 | + | ||
377 | + | ||
378 | + @Override | ||
379 | + public void updatePortStatistics(DeviceId deviceId, | ||
380 | + Collection<PortStatistics> portStatistics) { | ||
381 | + log.info("updatePortStatistics({}, {}) on Server called", deviceId, portStatistics); | ||
382 | + updatePortStatisticsDid = deviceId; | ||
383 | + updatePortStatisticsStats = portStatistics; | ||
384 | + updatePortStatistics.countDown(); | ||
385 | + } | ||
386 | + | ||
387 | + final CountDownLatch deviceDisconnected = new CountDownLatch(1); | ||
388 | + DeviceId deviceDisconnectedDid; | ||
389 | + | ||
390 | + @Override | ||
391 | + public void deviceDisconnected(DeviceId deviceId) { | ||
392 | + log.info("deviceDisconnected({}) on Server called", deviceId); | ||
393 | + deviceDisconnectedDid = deviceId; | ||
394 | + deviceDisconnected.countDown(); | ||
395 | + } | ||
396 | + } | ||
397 | + | ||
398 | +} |
-
Please register or login to post a comment