blob: d97e47ed42ef0e392b8e755faf84846837c7fdf1 [file] [log] [blame]
Jian Li5b402c72018-02-27 14:27:34 +09001/*
2 * Copyright 2018-present Open Networking Foundation
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 */
16package org.onosproject.openstacknode.codec;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.ObjectMapper;
20import com.fasterxml.jackson.databind.node.ObjectNode;
Jian Lie6312162018-03-21 21:41:00 +090021import com.google.common.collect.ImmutableList;
Jian Li5b402c72018-02-27 14:27:34 +090022import org.hamcrest.MatcherAssert;
23import org.junit.Before;
24import org.junit.Test;
25import org.onlab.packet.IpAddress;
26import org.onosproject.codec.CodecContext;
27import org.onosproject.codec.JsonCodec;
28import org.onosproject.codec.impl.CodecManager;
29import org.onosproject.core.CoreService;
30import org.onosproject.net.DeviceId;
Jian Li789fadb2018-07-10 13:59:47 +090031import org.onosproject.net.behaviour.ControllerInfo;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090032import org.onosproject.openstacknode.api.DefaultOpenstackAuth;
33import org.onosproject.openstacknode.api.DefaultOpenstackNode;
34import org.onosproject.openstacknode.api.DpdkConfig;
35import org.onosproject.openstacknode.api.DpdkInterface;
Jian Lic704b672018-09-04 18:52:53 +090036import org.onosproject.openstacknode.api.KeystoneConfig;
37import org.onosproject.openstacknode.api.NeutronConfig;
Jian Li5b402c72018-02-27 14:27:34 +090038import org.onosproject.openstacknode.api.NodeState;
Jian Li27841662018-04-14 01:59:47 +090039import org.onosproject.openstacknode.api.OpenstackAuth;
Jian Li5b402c72018-02-27 14:27:34 +090040import org.onosproject.openstacknode.api.OpenstackNode;
Jian Lie6312162018-03-21 21:41:00 +090041import org.onosproject.openstacknode.api.OpenstackPhyInterface;
Daniel Parkdeefa702018-07-17 17:55:51 +090042import org.onosproject.openstacknode.api.OpenstackSshAuth;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090043import org.onosproject.openstacknode.impl.DefaultDpdkConfig;
44import org.onosproject.openstacknode.impl.DefaultDpdkInterface;
Jian Lic704b672018-09-04 18:52:53 +090045import org.onosproject.openstacknode.api.DefaultKeystoneConfig;
46import org.onosproject.openstacknode.api.DefaultNeutronConfig;
Jian Lie6312162018-03-21 21:41:00 +090047import org.onosproject.openstacknode.impl.DefaultOpenstackPhyInterface;
Daniel Parkdeefa702018-07-17 17:55:51 +090048import org.onosproject.openstacknode.impl.DefaultOpenstackSshAuth;
Jian Li5b402c72018-02-27 14:27:34 +090049
50import java.io.IOException;
51import java.io.InputStream;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090052import java.util.ArrayList;
53import java.util.Collection;
Jian Li5b402c72018-02-27 14:27:34 +090054import java.util.HashMap;
55import java.util.Map;
56
57import static org.easymock.EasyMock.createMock;
58import static org.easymock.EasyMock.expect;
59import static org.easymock.EasyMock.replay;
60import static org.hamcrest.MatcherAssert.assertThat;
61import static org.hamcrest.Matchers.is;
62import static org.hamcrest.Matchers.notNullValue;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090063import static org.junit.Assert.assertEquals;
Jian Li5b402c72018-02-27 14:27:34 +090064import static org.onosproject.net.NetTestTools.APP_ID;
65import static org.onosproject.openstacknode.codec.OpenstackNodeJsonMatcher.matchesOpenstackNode;
66
67/**
68 * Unit tests for OpenstackNode codec.
69 */
70public class OpenstackNodeCodecTest {
71 MockCodecContext context;
Jian Lic704b672018-09-04 18:52:53 +090072
Jian Li5b402c72018-02-27 14:27:34 +090073 JsonCodec<OpenstackNode> openstackNodeCodec;
Jian Lie6312162018-03-21 21:41:00 +090074 JsonCodec<OpenstackPhyInterface> openstackPhyIntfJsonCodec;
Jian Li789fadb2018-07-10 13:59:47 +090075 JsonCodec<ControllerInfo> openstackControllerJsonCodec;
Jian Li27841662018-04-14 01:59:47 +090076 JsonCodec<OpenstackAuth> openstackAuthJsonCodec;
Daniel Parkdeefa702018-07-17 17:55:51 +090077 JsonCodec<OpenstackSshAuth> openstackSshAuthJsonCodec;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090078 JsonCodec<DpdkConfig> dpdkConfigJsonCodec;
79 JsonCodec<DpdkInterface> dpdkInterfaceJsonCodec;
Jian Lic704b672018-09-04 18:52:53 +090080 JsonCodec<KeystoneConfig> keystoneConfigJsonCodec;
81 JsonCodec<NeutronConfig> neutronConfigJsonCodec;
Daniel Parkdeefa702018-07-17 17:55:51 +090082
Jian Li5b402c72018-02-27 14:27:34 +090083 final CoreService mockCoreService = createMock(CoreService.class);
84 private static final String REST_APP_ID = "org.onosproject.rest";
85
86 @Before
87 public void setUp() {
88 context = new MockCodecContext();
89 openstackNodeCodec = new OpenstackNodeCodec();
Jian Lie6312162018-03-21 21:41:00 +090090 openstackPhyIntfJsonCodec = new OpenstackPhyInterfaceCodec();
Jian Li789fadb2018-07-10 13:59:47 +090091 openstackControllerJsonCodec = new OpenstackControllerCodec();
Jian Li27841662018-04-14 01:59:47 +090092 openstackAuthJsonCodec = new OpenstackAuthCodec();
Daniel Parkdeefa702018-07-17 17:55:51 +090093 openstackSshAuthJsonCodec = new OpenstackSshAuthCodec();
Daniel Parkd02d7bd2018-08-23 23:04:31 +090094 dpdkConfigJsonCodec = new DpdkConfigCodec();
95 dpdkInterfaceJsonCodec = new DpdkInterfaceCodec();
Jian Lic704b672018-09-04 18:52:53 +090096 keystoneConfigJsonCodec = new KeystoneConfigCodec();
97 neutronConfigJsonCodec = new NeutronConfigCodec();
Jian Lie6312162018-03-21 21:41:00 +090098
Jian Li5b402c72018-02-27 14:27:34 +090099 assertThat(openstackNodeCodec, notNullValue());
Jian Lie6312162018-03-21 21:41:00 +0900100 assertThat(openstackPhyIntfJsonCodec, notNullValue());
Jian Li789fadb2018-07-10 13:59:47 +0900101 assertThat(openstackControllerJsonCodec, notNullValue());
Jian Li27841662018-04-14 01:59:47 +0900102 assertThat(openstackAuthJsonCodec, notNullValue());
Daniel Parkdeefa702018-07-17 17:55:51 +0900103 assertThat(openstackSshAuthJsonCodec, notNullValue());
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900104 assertThat(dpdkConfigJsonCodec, notNullValue());
105 assertThat(dpdkInterfaceJsonCodec, notNullValue());
Jian Lic704b672018-09-04 18:52:53 +0900106 assertThat(keystoneConfigJsonCodec, notNullValue());
107 assertThat(neutronConfigJsonCodec, notNullValue());
Jian Li5b402c72018-02-27 14:27:34 +0900108
109 expect(mockCoreService.registerApplication(REST_APP_ID))
110 .andReturn(APP_ID).anyTimes();
111 replay(mockCoreService);
112 context.registerService(CoreService.class, mockCoreService);
113 }
114
Jian Li27841662018-04-14 01:59:47 +0900115 /**
116 * Tests the openstack compute node encoding.
117 */
Jian Li5b402c72018-02-27 14:27:34 +0900118 @Test
Jian Li27841662018-04-14 01:59:47 +0900119 public void testOpenstackComputeNodeEncode() {
Jian Lie6312162018-03-21 21:41:00 +0900120
121 OpenstackPhyInterface phyIntf1 = DefaultOpenstackPhyInterface.builder()
122 .network("mgmtnetwork")
123 .intf("eth3")
124 .build();
125 OpenstackPhyInterface phyIntf2 = DefaultOpenstackPhyInterface.builder()
126 .network("oamnetwork")
127 .intf("eth4")
128 .build();
129
Daniel Parkdeefa702018-07-17 17:55:51 +0900130 OpenstackSshAuth sshAuth = DefaultOpenstackSshAuth.builder()
131 .id("sdn")
132 .password("sdn")
133 .build();
134
Jian Li789fadb2018-07-10 13:59:47 +0900135 ControllerInfo controller1 =
136 new ControllerInfo(IpAddress.valueOf("10.10.10.2"), 6653, "tcp");
137 ControllerInfo controller2 =
138 new ControllerInfo(IpAddress.valueOf("10.10.10.3"), 6663, "tcp");
139
Jian Li5b402c72018-02-27 14:27:34 +0900140 OpenstackNode node = DefaultOpenstackNode.builder()
141 .hostname("compute")
142 .type(OpenstackNode.NodeType.COMPUTE)
143 .state(NodeState.INIT)
144 .managementIp(IpAddress.valueOf("10.10.10.1"))
145 .intgBridge(DeviceId.deviceId("br-int"))
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900146 .vlanIntf("vlan")
Jian Li5b402c72018-02-27 14:27:34 +0900147 .dataIp(IpAddress.valueOf("20.20.20.2"))
Jian Lie6312162018-03-21 21:41:00 +0900148 .phyIntfs(ImmutableList.of(phyIntf1, phyIntf2))
Jian Li789fadb2018-07-10 13:59:47 +0900149 .controllers(ImmutableList.of(controller1, controller2))
Daniel Parkdeefa702018-07-17 17:55:51 +0900150 .sshAuthInfo(sshAuth)
Jian Li5b402c72018-02-27 14:27:34 +0900151 .build();
152
153 ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
154 assertThat(nodeJson, matchesOpenstackNode(node));
155 }
156
Jian Li27841662018-04-14 01:59:47 +0900157 /**
158 * Tests the openstack compute node decoding.
159 *
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900160 * @throws IOException io exception
Jian Li27841662018-04-14 01:59:47 +0900161 */
Jian Li5b402c72018-02-27 14:27:34 +0900162 @Test
Jian Li27841662018-04-14 01:59:47 +0900163 public void testOpenstackComputeNodeDecode() throws IOException {
164 OpenstackNode node = getOpenstackNode("OpenstackComputeNode.json");
Jian Li5b402c72018-02-27 14:27:34 +0900165
166 assertThat(node.hostname(), is("compute-01"));
167 assertThat(node.type().name(), is("COMPUTE"));
168 assertThat(node.managementIp().toString(), is("172.16.130.4"));
169 assertThat(node.dataIp().toString(), is("172.16.130.4"));
170 assertThat(node.intgBridge().toString(), is("of:00000000000000a1"));
171 assertThat(node.vlanIntf(), is("eth2"));
Jian Lie6312162018-03-21 21:41:00 +0900172 assertThat(node.phyIntfs().size(), is(2));
Jian Li789fadb2018-07-10 13:59:47 +0900173 assertThat(node.controllers().size(), is(2));
Daniel Parkdeefa702018-07-17 17:55:51 +0900174 assertThat(node.sshAuthInfo().id(), is("sdn"));
175 assertThat(node.sshAuthInfo().password(), is("sdn"));
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900176 assertThat(node.datapathType(), is(DpdkConfig.DatapathType.NORMAL));
Daniel Park7e8c4d82018-08-13 23:47:49 +0900177
Jian Lie6312162018-03-21 21:41:00 +0900178
179 node.phyIntfs().forEach(intf -> {
180 if (intf.network().equals("mgmtnetwork")) {
181 assertThat(intf.intf(), is("eth3"));
182 }
183 if (intf.network().equals("oamnetwork")) {
184 assertThat(intf.intf(), is("eth4"));
185 }
186 });
Jian Li789fadb2018-07-10 13:59:47 +0900187
188 node.controllers().forEach(ctrl -> {
189 if (ctrl.ip().toString().equals("10.10.10.2")) {
190 assertThat(ctrl.port(), is(6653));
191 }
192 if (ctrl.ip().toString().equals("10.10.10.3")) {
193 assertThat(ctrl.port(), is(6663));
194 }
195 });
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900196 }
Daniel Park92abf312018-08-08 17:01:35 +0900197
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900198 /**
199 * Tests the openstack compute node encoding with dpdk config.
200 */
201 @Test
202 public void testOpenstackDpdkComputeNodeEncode() {
203 DpdkInterface dpdkInterface1 = DefaultDpdkInterface.builder()
204 .deviceName("br-int")
205 .intf("dpdk0")
206 .mtu(Long.valueOf(1600))
207 .pciAddress("0000:85:00.0")
208 .type(DpdkInterface.Type.DPDK)
209 .build();
Daniel Park92abf312018-08-08 17:01:35 +0900210
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900211 DpdkInterface dpdkInterface2 = DefaultDpdkInterface.builder()
212 .deviceName("br-tun")
213 .intf("dpdk1")
214 .pciAddress("0000:85:00.1")
215 .type(DpdkInterface.Type.DPDK)
216 .build();
217
218 Collection<DpdkInterface> dpdkInterfaceCollection = new ArrayList<>();
219 dpdkInterfaceCollection.add(dpdkInterface1);
220 dpdkInterfaceCollection.add(dpdkInterface2);
221
222
223 DpdkConfig dpdkConfig = DefaultDpdkConfig.builder()
224 .datapathType(DpdkConfig.DatapathType.NETDEV)
225 .dpdkIntfs(dpdkInterfaceCollection)
226 .build();
227
228 OpenstackNode node = DefaultOpenstackNode.builder()
229 .hostname("compute")
230 .type(OpenstackNode.NodeType.COMPUTE)
231 .state(NodeState.INIT)
232 .managementIp(IpAddress.valueOf("10.10.10.1"))
233 .intgBridge(DeviceId.deviceId("br-int"))
234 .vlanIntf("vlan")
235 .dataIp(IpAddress.valueOf("20.20.20.2"))
236 .dpdkConfig(dpdkConfig)
237 .build();
238
239 ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
240 assertThat(nodeJson, matchesOpenstackNode(node));
241 }
242
243 /**
244 * Tests the openstack compute node decoding with dpdk config.
245 *
246 * @throws IOException io exception
247 */
248 @Test
249 public void testOpenstackDpdkComputeNodeDecode() throws IOException {
250 OpenstackNode node = getOpenstackNode("OpenstackDpdkComputeNode.json");
251
252 assertEquals(node.datapathType(), DpdkConfig.DatapathType.NETDEV);
253 assertEquals(node.socketDir(), "/var/lib/libvirt/qemu");
254 assertEquals(node.dpdkConfig().dpdkIntfs().size(), 2);
Jian Li5b402c72018-02-27 14:27:34 +0900255 }
256
257 /**
Jian Li27841662018-04-14 01:59:47 +0900258 * Tests the openstack controller node encoding.
259 */
260 @Test
261 public void testOpenstackControllerNodeEncode() {
262 OpenstackAuth auth = DefaultOpenstackAuth.builder()
263 .version("v2.0")
Jian Li27841662018-04-14 01:59:47 +0900264 .protocol(OpenstackAuth.Protocol.HTTP)
265 .project("admin")
266 .username("admin")
267 .password("nova")
268 .perspective(OpenstackAuth.Perspective.PUBLIC)
269 .build();
270
Jian Lic704b672018-09-04 18:52:53 +0900271 String endpoint = "172.16.130.10:35357/v2.0";
272
273 KeystoneConfig keystoneConfig = DefaultKeystoneConfig.builder()
274 .endpoint(endpoint)
275 .authentication(auth)
276 .build();
277
278 NeutronConfig neutronConfig = DefaultNeutronConfig.builder()
279 .useMetadataProxy(true)
280 .metadataProxySecret("onos")
281 .build();
282
Jian Li27841662018-04-14 01:59:47 +0900283 OpenstackNode node = DefaultOpenstackNode.builder()
284 .hostname("controller")
285 .type(OpenstackNode.NodeType.CONTROLLER)
286 .state(NodeState.INIT)
287 .managementIp(IpAddress.valueOf("172.16.130.10"))
Jian Lic704b672018-09-04 18:52:53 +0900288 .keystoneConfig(keystoneConfig)
289 .neutronConfig(neutronConfig)
Jian Li27841662018-04-14 01:59:47 +0900290 .build();
291
292 ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
293 assertThat(nodeJson, matchesOpenstackNode(node));
294 }
295
296 /**
297 * Tests the openstack controller node decoding.
298 */
299 @Test
300 public void testOpenstackControllerNodeDecode() throws IOException {
301 OpenstackNode node = getOpenstackNode("OpenstackControllerNode.json");
302
303 assertThat(node.hostname(), is("controller"));
304 assertThat(node.type().name(), is("CONTROLLER"));
305 assertThat(node.managementIp().toString(), is("172.16.130.10"));
306
Jian Lic704b672018-09-04 18:52:53 +0900307 KeystoneConfig keystoneConfig = node.keystoneConfig();
308 OpenstackAuth auth = keystoneConfig.authentication();
309 String endpoint = keystoneConfig.endpoint();
Jian Li27841662018-04-14 01:59:47 +0900310
311 assertThat(auth.version(), is("v2.0"));
Jian Li27841662018-04-14 01:59:47 +0900312 assertThat(auth.protocol(), is(OpenstackAuth.Protocol.HTTP));
313 assertThat(auth.username(), is("admin"));
314 assertThat(auth.password(), is("nova"));
315 assertThat(auth.project(), is("admin"));
316 assertThat(auth.perspective(), is(OpenstackAuth.Perspective.PUBLIC));
Jian Lic704b672018-09-04 18:52:53 +0900317
318 assertThat(endpoint, is("172.16.130.10:35357/v2.0"));
319
320 NeutronConfig neutronConfig = node.neutronConfig();
321
322 assertThat(neutronConfig.useMetadataProxy(), is(true));
323 assertThat(neutronConfig.metadataProxySecret(), is("onos"));
324 }
325
326 /**
327 * Tests the openstack obsolete controller node decoding.
328 */
329 @Test
330 public void testOpenstackObsoleteControllerNodeDecode() throws IOException {
331 OpenstackNode node = getOpenstackNode("OpenstackObsoleteControllerNode.json");
332
333 assertThat(node.hostname(), is("controller"));
334 assertThat(node.type().name(), is("CONTROLLER"));
335 assertThat(node.managementIp().toString(), is("172.16.130.10"));
336
337 KeystoneConfig keystoneConfig = node.keystoneConfig();
338 OpenstackAuth auth = keystoneConfig.authentication();
339 String endpoint = keystoneConfig.endpoint();
340
341 assertThat(auth.version(), is("v2.0"));
342 assertThat(auth.protocol(), is(OpenstackAuth.Protocol.HTTP));
343 assertThat(auth.username(), is("admin"));
344 assertThat(auth.password(), is("nova"));
345 assertThat(auth.project(), is("admin"));
346 assertThat(auth.perspective(), is(OpenstackAuth.Perspective.PUBLIC));
347
348 assertThat(endpoint, is("172.16.130.10:35357/v2.0"));
Jian Li27841662018-04-14 01:59:47 +0900349 }
350
351 /**
Jian Li5b402c72018-02-27 14:27:34 +0900352 * Reads in an openstack node from the given resource and decodes it.
353 *
354 * @param resourceName resource to use to read the JSON for the rule
355 * @return decoded openstack node
356 * @throws IOException if processing the resource fails
357 */
358 private OpenstackNode getOpenstackNode(String resourceName) throws IOException {
359 InputStream jsonStream = OpenstackNodeCodecTest.class.getResourceAsStream(resourceName);
360 JsonNode json = context.mapper().readTree(jsonStream);
361 MatcherAssert.assertThat(json, notNullValue());
362 OpenstackNode node = openstackNodeCodec.decode((ObjectNode) json, context);
363 assertThat(node, notNullValue());
364 return node;
365 }
366
367 /**
368 * Mock codec context for use in codec unit tests.
369 */
370 private class MockCodecContext implements CodecContext {
371 private final ObjectMapper mapper = new ObjectMapper();
372 private final CodecManager manager = new CodecManager();
373 private final Map<Class<?>, Object> services = new HashMap<>();
374
375 /**
376 * Constructs a new mock codec context.
377 */
378 public MockCodecContext() {
379 manager.activate();
380 }
381
382 @Override
383 public ObjectMapper mapper() {
384 return mapper;
385 }
386
387 @Override
388 @SuppressWarnings("unchecked")
389 public <T> JsonCodec<T> codec(Class<T> entityClass) {
Jian Lie6312162018-03-21 21:41:00 +0900390 if (entityClass == OpenstackPhyInterface.class) {
391 return (JsonCodec<T>) openstackPhyIntfJsonCodec;
392 }
Jian Li789fadb2018-07-10 13:59:47 +0900393 if (entityClass == ControllerInfo.class) {
394 return (JsonCodec<T>) openstackControllerJsonCodec;
395 }
Jian Li27841662018-04-14 01:59:47 +0900396 if (entityClass == OpenstackAuth.class) {
397 return (JsonCodec<T>) openstackAuthJsonCodec;
398 }
Daniel Parkdeefa702018-07-17 17:55:51 +0900399 if (entityClass == OpenstackSshAuth.class) {
400 return (JsonCodec<T>) openstackSshAuthJsonCodec;
401 }
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900402 if (entityClass == DpdkConfig.class) {
403 return (JsonCodec<T>) dpdkConfigJsonCodec;
404 }
405 if (entityClass == DpdkInterface.class) {
406 return (JsonCodec<T>) dpdkInterfaceJsonCodec;
407 }
Jian Lic704b672018-09-04 18:52:53 +0900408 if (entityClass == KeystoneConfig.class) {
409 return (JsonCodec<T>) keystoneConfigJsonCodec;
410 }
411 if (entityClass == NeutronConfig.class) {
412 return (JsonCodec<T>) neutronConfigJsonCodec;
413 }
Jian Li5b402c72018-02-27 14:27:34 +0900414 return manager.getCodec(entityClass);
415 }
416
417 @SuppressWarnings("unchecked")
418 @Override
419 public <T> T getService(Class<T> serviceClass) {
420 return (T) services.get(serviceClass);
421 }
422
423 // for registering mock services
424 public <T> void registerService(Class<T> serviceClass, T impl) {
425 services.put(serviceClass, impl);
426 }
427 }
428}