blob: af5fdf404985a5482a33272e565d61957953978f [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 Li5b402c72018-02-27 14:27:34 +090036import org.onosproject.openstacknode.api.NodeState;
Jian Li27841662018-04-14 01:59:47 +090037import org.onosproject.openstacknode.api.OpenstackAuth;
Jian Li5b402c72018-02-27 14:27:34 +090038import org.onosproject.openstacknode.api.OpenstackNode;
Jian Lie6312162018-03-21 21:41:00 +090039import org.onosproject.openstacknode.api.OpenstackPhyInterface;
Daniel Parkdeefa702018-07-17 17:55:51 +090040import org.onosproject.openstacknode.api.OpenstackSshAuth;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090041import org.onosproject.openstacknode.impl.DefaultDpdkConfig;
42import org.onosproject.openstacknode.impl.DefaultDpdkInterface;
Jian Lie6312162018-03-21 21:41:00 +090043import org.onosproject.openstacknode.impl.DefaultOpenstackPhyInterface;
Daniel Parkdeefa702018-07-17 17:55:51 +090044import org.onosproject.openstacknode.impl.DefaultOpenstackSshAuth;
Jian Li5b402c72018-02-27 14:27:34 +090045
46import java.io.IOException;
47import java.io.InputStream;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090048import java.util.ArrayList;
49import java.util.Collection;
Jian Li5b402c72018-02-27 14:27:34 +090050import java.util.HashMap;
51import java.util.Map;
52
53import static org.easymock.EasyMock.createMock;
54import static org.easymock.EasyMock.expect;
55import static org.easymock.EasyMock.replay;
56import static org.hamcrest.MatcherAssert.assertThat;
57import static org.hamcrest.Matchers.is;
58import static org.hamcrest.Matchers.notNullValue;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090059import static org.junit.Assert.assertEquals;
Jian Li5b402c72018-02-27 14:27:34 +090060import static org.onosproject.net.NetTestTools.APP_ID;
61import static org.onosproject.openstacknode.codec.OpenstackNodeJsonMatcher.matchesOpenstackNode;
62
63/**
64 * Unit tests for OpenstackNode codec.
65 */
66public class OpenstackNodeCodecTest {
67 MockCodecContext context;
68 JsonCodec<OpenstackNode> openstackNodeCodec;
Jian Lie6312162018-03-21 21:41:00 +090069 JsonCodec<OpenstackPhyInterface> openstackPhyIntfJsonCodec;
Jian Li789fadb2018-07-10 13:59:47 +090070 JsonCodec<ControllerInfo> openstackControllerJsonCodec;
Jian Li27841662018-04-14 01:59:47 +090071 JsonCodec<OpenstackAuth> openstackAuthJsonCodec;
Daniel Parkdeefa702018-07-17 17:55:51 +090072 JsonCodec<OpenstackSshAuth> openstackSshAuthJsonCodec;
Daniel Parkd02d7bd2018-08-23 23:04:31 +090073 JsonCodec<DpdkConfig> dpdkConfigJsonCodec;
74 JsonCodec<DpdkInterface> dpdkInterfaceJsonCodec;
Daniel Parkdeefa702018-07-17 17:55:51 +090075
Jian Li5b402c72018-02-27 14:27:34 +090076 final CoreService mockCoreService = createMock(CoreService.class);
77 private static final String REST_APP_ID = "org.onosproject.rest";
78
79 @Before
80 public void setUp() {
81 context = new MockCodecContext();
82 openstackNodeCodec = new OpenstackNodeCodec();
Jian Lie6312162018-03-21 21:41:00 +090083 openstackPhyIntfJsonCodec = new OpenstackPhyInterfaceCodec();
Jian Li789fadb2018-07-10 13:59:47 +090084 openstackControllerJsonCodec = new OpenstackControllerCodec();
Jian Li27841662018-04-14 01:59:47 +090085 openstackAuthJsonCodec = new OpenstackAuthCodec();
Daniel Parkdeefa702018-07-17 17:55:51 +090086 openstackSshAuthJsonCodec = new OpenstackSshAuthCodec();
Daniel Parkd02d7bd2018-08-23 23:04:31 +090087 dpdkConfigJsonCodec = new DpdkConfigCodec();
88 dpdkInterfaceJsonCodec = new DpdkInterfaceCodec();
Jian Lie6312162018-03-21 21:41:00 +090089
Jian Li5b402c72018-02-27 14:27:34 +090090 assertThat(openstackNodeCodec, notNullValue());
Jian Lie6312162018-03-21 21:41:00 +090091 assertThat(openstackPhyIntfJsonCodec, notNullValue());
Jian Li789fadb2018-07-10 13:59:47 +090092 assertThat(openstackControllerJsonCodec, notNullValue());
Jian Li27841662018-04-14 01:59:47 +090093 assertThat(openstackAuthJsonCodec, notNullValue());
Daniel Parkdeefa702018-07-17 17:55:51 +090094 assertThat(openstackSshAuthJsonCodec, notNullValue());
Daniel Parkd02d7bd2018-08-23 23:04:31 +090095 assertThat(dpdkConfigJsonCodec, notNullValue());
96 assertThat(dpdkInterfaceJsonCodec, notNullValue());
Jian Li5b402c72018-02-27 14:27:34 +090097
98 expect(mockCoreService.registerApplication(REST_APP_ID))
99 .andReturn(APP_ID).anyTimes();
100 replay(mockCoreService);
101 context.registerService(CoreService.class, mockCoreService);
102 }
103
Jian Li27841662018-04-14 01:59:47 +0900104 /**
105 * Tests the openstack compute node encoding.
106 */
Jian Li5b402c72018-02-27 14:27:34 +0900107 @Test
Jian Li27841662018-04-14 01:59:47 +0900108 public void testOpenstackComputeNodeEncode() {
Jian Lie6312162018-03-21 21:41:00 +0900109
110 OpenstackPhyInterface phyIntf1 = DefaultOpenstackPhyInterface.builder()
111 .network("mgmtnetwork")
112 .intf("eth3")
113 .build();
114 OpenstackPhyInterface phyIntf2 = DefaultOpenstackPhyInterface.builder()
115 .network("oamnetwork")
116 .intf("eth4")
117 .build();
118
Daniel Parkdeefa702018-07-17 17:55:51 +0900119 OpenstackSshAuth sshAuth = DefaultOpenstackSshAuth.builder()
120 .id("sdn")
121 .password("sdn")
122 .build();
123
Jian Li789fadb2018-07-10 13:59:47 +0900124 ControllerInfo controller1 =
125 new ControllerInfo(IpAddress.valueOf("10.10.10.2"), 6653, "tcp");
126 ControllerInfo controller2 =
127 new ControllerInfo(IpAddress.valueOf("10.10.10.3"), 6663, "tcp");
128
Jian Li5b402c72018-02-27 14:27:34 +0900129 OpenstackNode node = DefaultOpenstackNode.builder()
130 .hostname("compute")
131 .type(OpenstackNode.NodeType.COMPUTE)
132 .state(NodeState.INIT)
133 .managementIp(IpAddress.valueOf("10.10.10.1"))
134 .intgBridge(DeviceId.deviceId("br-int"))
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900135 .vlanIntf("vlan")
Jian Li5b402c72018-02-27 14:27:34 +0900136 .dataIp(IpAddress.valueOf("20.20.20.2"))
Jian Lie6312162018-03-21 21:41:00 +0900137 .phyIntfs(ImmutableList.of(phyIntf1, phyIntf2))
Jian Li789fadb2018-07-10 13:59:47 +0900138 .controllers(ImmutableList.of(controller1, controller2))
Daniel Parkdeefa702018-07-17 17:55:51 +0900139 .sshAuthInfo(sshAuth)
Jian Li5b402c72018-02-27 14:27:34 +0900140 .build();
141
142 ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
143 assertThat(nodeJson, matchesOpenstackNode(node));
144 }
145
Jian Li27841662018-04-14 01:59:47 +0900146 /**
147 * Tests the openstack compute node decoding.
148 *
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900149 * @throws IOException io exception
Jian Li27841662018-04-14 01:59:47 +0900150 */
Jian Li5b402c72018-02-27 14:27:34 +0900151 @Test
Jian Li27841662018-04-14 01:59:47 +0900152 public void testOpenstackComputeNodeDecode() throws IOException {
153 OpenstackNode node = getOpenstackNode("OpenstackComputeNode.json");
Jian Li5b402c72018-02-27 14:27:34 +0900154
155 assertThat(node.hostname(), is("compute-01"));
156 assertThat(node.type().name(), is("COMPUTE"));
157 assertThat(node.managementIp().toString(), is("172.16.130.4"));
158 assertThat(node.dataIp().toString(), is("172.16.130.4"));
159 assertThat(node.intgBridge().toString(), is("of:00000000000000a1"));
160 assertThat(node.vlanIntf(), is("eth2"));
Jian Lie6312162018-03-21 21:41:00 +0900161 assertThat(node.phyIntfs().size(), is(2));
Jian Li789fadb2018-07-10 13:59:47 +0900162 assertThat(node.controllers().size(), is(2));
Daniel Parkdeefa702018-07-17 17:55:51 +0900163 assertThat(node.sshAuthInfo().id(), is("sdn"));
164 assertThat(node.sshAuthInfo().password(), is("sdn"));
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900165 assertThat(node.datapathType(), is(DpdkConfig.DatapathType.NORMAL));
Daniel Park7e8c4d82018-08-13 23:47:49 +0900166
Jian Lie6312162018-03-21 21:41:00 +0900167
168 node.phyIntfs().forEach(intf -> {
169 if (intf.network().equals("mgmtnetwork")) {
170 assertThat(intf.intf(), is("eth3"));
171 }
172 if (intf.network().equals("oamnetwork")) {
173 assertThat(intf.intf(), is("eth4"));
174 }
175 });
Jian Li789fadb2018-07-10 13:59:47 +0900176
177 node.controllers().forEach(ctrl -> {
178 if (ctrl.ip().toString().equals("10.10.10.2")) {
179 assertThat(ctrl.port(), is(6653));
180 }
181 if (ctrl.ip().toString().equals("10.10.10.3")) {
182 assertThat(ctrl.port(), is(6663));
183 }
184 });
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900185 }
Daniel Park92abf312018-08-08 17:01:35 +0900186
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900187 /**
188 * Tests the openstack compute node encoding with dpdk config.
189 */
190 @Test
191 public void testOpenstackDpdkComputeNodeEncode() {
192 DpdkInterface dpdkInterface1 = DefaultDpdkInterface.builder()
193 .deviceName("br-int")
194 .intf("dpdk0")
195 .mtu(Long.valueOf(1600))
196 .pciAddress("0000:85:00.0")
197 .type(DpdkInterface.Type.DPDK)
198 .build();
Daniel Park92abf312018-08-08 17:01:35 +0900199
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900200 DpdkInterface dpdkInterface2 = DefaultDpdkInterface.builder()
201 .deviceName("br-tun")
202 .intf("dpdk1")
203 .pciAddress("0000:85:00.1")
204 .type(DpdkInterface.Type.DPDK)
205 .build();
206
207 Collection<DpdkInterface> dpdkInterfaceCollection = new ArrayList<>();
208 dpdkInterfaceCollection.add(dpdkInterface1);
209 dpdkInterfaceCollection.add(dpdkInterface2);
210
211
212 DpdkConfig dpdkConfig = DefaultDpdkConfig.builder()
213 .datapathType(DpdkConfig.DatapathType.NETDEV)
214 .dpdkIntfs(dpdkInterfaceCollection)
215 .build();
216
217 OpenstackNode node = DefaultOpenstackNode.builder()
218 .hostname("compute")
219 .type(OpenstackNode.NodeType.COMPUTE)
220 .state(NodeState.INIT)
221 .managementIp(IpAddress.valueOf("10.10.10.1"))
222 .intgBridge(DeviceId.deviceId("br-int"))
223 .vlanIntf("vlan")
224 .dataIp(IpAddress.valueOf("20.20.20.2"))
225 .dpdkConfig(dpdkConfig)
226 .build();
227
228 ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
229 assertThat(nodeJson, matchesOpenstackNode(node));
230 }
231
232 /**
233 * Tests the openstack compute node decoding with dpdk config.
234 *
235 * @throws IOException io exception
236 */
237 @Test
238 public void testOpenstackDpdkComputeNodeDecode() throws IOException {
239 OpenstackNode node = getOpenstackNode("OpenstackDpdkComputeNode.json");
240
241 assertEquals(node.datapathType(), DpdkConfig.DatapathType.NETDEV);
242 assertEquals(node.socketDir(), "/var/lib/libvirt/qemu");
243 assertEquals(node.dpdkConfig().dpdkIntfs().size(), 2);
Jian Li5b402c72018-02-27 14:27:34 +0900244 }
245
246 /**
Jian Li27841662018-04-14 01:59:47 +0900247 * Tests the openstack controller node encoding.
248 */
249 @Test
250 public void testOpenstackControllerNodeEncode() {
251 OpenstackAuth auth = DefaultOpenstackAuth.builder()
252 .version("v2.0")
Jian Li27841662018-04-14 01:59:47 +0900253 .protocol(OpenstackAuth.Protocol.HTTP)
254 .project("admin")
255 .username("admin")
256 .password("nova")
257 .perspective(OpenstackAuth.Perspective.PUBLIC)
258 .build();
259
260 OpenstackNode node = DefaultOpenstackNode.builder()
261 .hostname("controller")
262 .type(OpenstackNode.NodeType.CONTROLLER)
263 .state(NodeState.INIT)
264 .managementIp(IpAddress.valueOf("172.16.130.10"))
Jian Li6d410362018-08-17 09:41:08 +0900265 .endpoint("keystone-end-point-url")
Jian Li27841662018-04-14 01:59:47 +0900266 .authentication(auth)
267 .build();
268
269 ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
270 assertThat(nodeJson, matchesOpenstackNode(node));
271 }
272
273 /**
274 * Tests the openstack controller node decoding.
275 */
276 @Test
277 public void testOpenstackControllerNodeDecode() throws IOException {
278 OpenstackNode node = getOpenstackNode("OpenstackControllerNode.json");
279
280 assertThat(node.hostname(), is("controller"));
281 assertThat(node.type().name(), is("CONTROLLER"));
282 assertThat(node.managementIp().toString(), is("172.16.130.10"));
Jian Li6d410362018-08-17 09:41:08 +0900283 assertThat(node.endpoint(), is("keystone-end-point-url"));
Jian Li27841662018-04-14 01:59:47 +0900284
285 OpenstackAuth auth = node.authentication();
286
287 assertThat(auth.version(), is("v2.0"));
Jian Li27841662018-04-14 01:59:47 +0900288 assertThat(auth.protocol(), is(OpenstackAuth.Protocol.HTTP));
289 assertThat(auth.username(), is("admin"));
290 assertThat(auth.password(), is("nova"));
291 assertThat(auth.project(), is("admin"));
292 assertThat(auth.perspective(), is(OpenstackAuth.Perspective.PUBLIC));
293 }
294
295 /**
Jian Li5b402c72018-02-27 14:27:34 +0900296 * Reads in an openstack node from the given resource and decodes it.
297 *
298 * @param resourceName resource to use to read the JSON for the rule
299 * @return decoded openstack node
300 * @throws IOException if processing the resource fails
301 */
302 private OpenstackNode getOpenstackNode(String resourceName) throws IOException {
303 InputStream jsonStream = OpenstackNodeCodecTest.class.getResourceAsStream(resourceName);
304 JsonNode json = context.mapper().readTree(jsonStream);
305 MatcherAssert.assertThat(json, notNullValue());
306 OpenstackNode node = openstackNodeCodec.decode((ObjectNode) json, context);
307 assertThat(node, notNullValue());
308 return node;
309 }
310
311 /**
312 * Mock codec context for use in codec unit tests.
313 */
314 private class MockCodecContext implements CodecContext {
315 private final ObjectMapper mapper = new ObjectMapper();
316 private final CodecManager manager = new CodecManager();
317 private final Map<Class<?>, Object> services = new HashMap<>();
318
319 /**
320 * Constructs a new mock codec context.
321 */
322 public MockCodecContext() {
323 manager.activate();
324 }
325
326 @Override
327 public ObjectMapper mapper() {
328 return mapper;
329 }
330
331 @Override
332 @SuppressWarnings("unchecked")
333 public <T> JsonCodec<T> codec(Class<T> entityClass) {
Jian Lie6312162018-03-21 21:41:00 +0900334 if (entityClass == OpenstackPhyInterface.class) {
335 return (JsonCodec<T>) openstackPhyIntfJsonCodec;
336 }
Jian Li789fadb2018-07-10 13:59:47 +0900337 if (entityClass == ControllerInfo.class) {
338 return (JsonCodec<T>) openstackControllerJsonCodec;
339 }
Jian Li27841662018-04-14 01:59:47 +0900340 if (entityClass == OpenstackAuth.class) {
341 return (JsonCodec<T>) openstackAuthJsonCodec;
342 }
Daniel Parkdeefa702018-07-17 17:55:51 +0900343 if (entityClass == OpenstackSshAuth.class) {
344 return (JsonCodec<T>) openstackSshAuthJsonCodec;
345 }
Daniel Parkd02d7bd2018-08-23 23:04:31 +0900346 if (entityClass == DpdkConfig.class) {
347 return (JsonCodec<T>) dpdkConfigJsonCodec;
348 }
349 if (entityClass == DpdkInterface.class) {
350 return (JsonCodec<T>) dpdkInterfaceJsonCodec;
351 }
Jian Li5b402c72018-02-27 14:27:34 +0900352 return manager.getCodec(entityClass);
353 }
354
355 @SuppressWarnings("unchecked")
356 @Override
357 public <T> T getService(Class<T> serviceClass) {
358 return (T) services.get(serviceClass);
359 }
360
361 // for registering mock services
362 public <T> void registerService(Class<T> serviceClass, T impl) {
363 services.put(serviceClass, impl);
364 }
365 }
366}