blob: af5fdf404985a5482a33272e565d61957953978f [file] [log] [blame]
/*
* Copyright 2018-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.openstacknode.codec;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableList;
import org.hamcrest.MatcherAssert;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.core.CoreService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.openstacknode.api.DefaultOpenstackAuth;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.DpdkConfig;
import org.onosproject.openstacknode.api.DpdkInterface;
import org.onosproject.openstacknode.api.NodeState;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackNode;
import org.onosproject.openstacknode.api.OpenstackPhyInterface;
import org.onosproject.openstacknode.api.OpenstackSshAuth;
import org.onosproject.openstacknode.impl.DefaultDpdkConfig;
import org.onosproject.openstacknode.impl.DefaultDpdkInterface;
import org.onosproject.openstacknode.impl.DefaultOpenstackPhyInterface;
import org.onosproject.openstacknode.impl.DefaultOpenstackSshAuth;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.openstacknode.codec.OpenstackNodeJsonMatcher.matchesOpenstackNode;
/**
* Unit tests for OpenstackNode codec.
*/
public class OpenstackNodeCodecTest {
MockCodecContext context;
JsonCodec<OpenstackNode> openstackNodeCodec;
JsonCodec<OpenstackPhyInterface> openstackPhyIntfJsonCodec;
JsonCodec<ControllerInfo> openstackControllerJsonCodec;
JsonCodec<OpenstackAuth> openstackAuthJsonCodec;
JsonCodec<OpenstackSshAuth> openstackSshAuthJsonCodec;
JsonCodec<DpdkConfig> dpdkConfigJsonCodec;
JsonCodec<DpdkInterface> dpdkInterfaceJsonCodec;
final CoreService mockCoreService = createMock(CoreService.class);
private static final String REST_APP_ID = "org.onosproject.rest";
@Before
public void setUp() {
context = new MockCodecContext();
openstackNodeCodec = new OpenstackNodeCodec();
openstackPhyIntfJsonCodec = new OpenstackPhyInterfaceCodec();
openstackControllerJsonCodec = new OpenstackControllerCodec();
openstackAuthJsonCodec = new OpenstackAuthCodec();
openstackSshAuthJsonCodec = new OpenstackSshAuthCodec();
dpdkConfigJsonCodec = new DpdkConfigCodec();
dpdkInterfaceJsonCodec = new DpdkInterfaceCodec();
assertThat(openstackNodeCodec, notNullValue());
assertThat(openstackPhyIntfJsonCodec, notNullValue());
assertThat(openstackControllerJsonCodec, notNullValue());
assertThat(openstackAuthJsonCodec, notNullValue());
assertThat(openstackSshAuthJsonCodec, notNullValue());
assertThat(dpdkConfigJsonCodec, notNullValue());
assertThat(dpdkInterfaceJsonCodec, notNullValue());
expect(mockCoreService.registerApplication(REST_APP_ID))
.andReturn(APP_ID).anyTimes();
replay(mockCoreService);
context.registerService(CoreService.class, mockCoreService);
}
/**
* Tests the openstack compute node encoding.
*/
@Test
public void testOpenstackComputeNodeEncode() {
OpenstackPhyInterface phyIntf1 = DefaultOpenstackPhyInterface.builder()
.network("mgmtnetwork")
.intf("eth3")
.build();
OpenstackPhyInterface phyIntf2 = DefaultOpenstackPhyInterface.builder()
.network("oamnetwork")
.intf("eth4")
.build();
OpenstackSshAuth sshAuth = DefaultOpenstackSshAuth.builder()
.id("sdn")
.password("sdn")
.build();
ControllerInfo controller1 =
new ControllerInfo(IpAddress.valueOf("10.10.10.2"), 6653, "tcp");
ControllerInfo controller2 =
new ControllerInfo(IpAddress.valueOf("10.10.10.3"), 6663, "tcp");
OpenstackNode node = DefaultOpenstackNode.builder()
.hostname("compute")
.type(OpenstackNode.NodeType.COMPUTE)
.state(NodeState.INIT)
.managementIp(IpAddress.valueOf("10.10.10.1"))
.intgBridge(DeviceId.deviceId("br-int"))
.vlanIntf("vlan")
.dataIp(IpAddress.valueOf("20.20.20.2"))
.phyIntfs(ImmutableList.of(phyIntf1, phyIntf2))
.controllers(ImmutableList.of(controller1, controller2))
.sshAuthInfo(sshAuth)
.build();
ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
assertThat(nodeJson, matchesOpenstackNode(node));
}
/**
* Tests the openstack compute node decoding.
*
* @throws IOException io exception
*/
@Test
public void testOpenstackComputeNodeDecode() throws IOException {
OpenstackNode node = getOpenstackNode("OpenstackComputeNode.json");
assertThat(node.hostname(), is("compute-01"));
assertThat(node.type().name(), is("COMPUTE"));
assertThat(node.managementIp().toString(), is("172.16.130.4"));
assertThat(node.dataIp().toString(), is("172.16.130.4"));
assertThat(node.intgBridge().toString(), is("of:00000000000000a1"));
assertThat(node.vlanIntf(), is("eth2"));
assertThat(node.phyIntfs().size(), is(2));
assertThat(node.controllers().size(), is(2));
assertThat(node.sshAuthInfo().id(), is("sdn"));
assertThat(node.sshAuthInfo().password(), is("sdn"));
assertThat(node.datapathType(), is(DpdkConfig.DatapathType.NORMAL));
node.phyIntfs().forEach(intf -> {
if (intf.network().equals("mgmtnetwork")) {
assertThat(intf.intf(), is("eth3"));
}
if (intf.network().equals("oamnetwork")) {
assertThat(intf.intf(), is("eth4"));
}
});
node.controllers().forEach(ctrl -> {
if (ctrl.ip().toString().equals("10.10.10.2")) {
assertThat(ctrl.port(), is(6653));
}
if (ctrl.ip().toString().equals("10.10.10.3")) {
assertThat(ctrl.port(), is(6663));
}
});
}
/**
* Tests the openstack compute node encoding with dpdk config.
*/
@Test
public void testOpenstackDpdkComputeNodeEncode() {
DpdkInterface dpdkInterface1 = DefaultDpdkInterface.builder()
.deviceName("br-int")
.intf("dpdk0")
.mtu(Long.valueOf(1600))
.pciAddress("0000:85:00.0")
.type(DpdkInterface.Type.DPDK)
.build();
DpdkInterface dpdkInterface2 = DefaultDpdkInterface.builder()
.deviceName("br-tun")
.intf("dpdk1")
.pciAddress("0000:85:00.1")
.type(DpdkInterface.Type.DPDK)
.build();
Collection<DpdkInterface> dpdkInterfaceCollection = new ArrayList<>();
dpdkInterfaceCollection.add(dpdkInterface1);
dpdkInterfaceCollection.add(dpdkInterface2);
DpdkConfig dpdkConfig = DefaultDpdkConfig.builder()
.datapathType(DpdkConfig.DatapathType.NETDEV)
.dpdkIntfs(dpdkInterfaceCollection)
.build();
OpenstackNode node = DefaultOpenstackNode.builder()
.hostname("compute")
.type(OpenstackNode.NodeType.COMPUTE)
.state(NodeState.INIT)
.managementIp(IpAddress.valueOf("10.10.10.1"))
.intgBridge(DeviceId.deviceId("br-int"))
.vlanIntf("vlan")
.dataIp(IpAddress.valueOf("20.20.20.2"))
.dpdkConfig(dpdkConfig)
.build();
ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
assertThat(nodeJson, matchesOpenstackNode(node));
}
/**
* Tests the openstack compute node decoding with dpdk config.
*
* @throws IOException io exception
*/
@Test
public void testOpenstackDpdkComputeNodeDecode() throws IOException {
OpenstackNode node = getOpenstackNode("OpenstackDpdkComputeNode.json");
assertEquals(node.datapathType(), DpdkConfig.DatapathType.NETDEV);
assertEquals(node.socketDir(), "/var/lib/libvirt/qemu");
assertEquals(node.dpdkConfig().dpdkIntfs().size(), 2);
}
/**
* Tests the openstack controller node encoding.
*/
@Test
public void testOpenstackControllerNodeEncode() {
OpenstackAuth auth = DefaultOpenstackAuth.builder()
.version("v2.0")
.protocol(OpenstackAuth.Protocol.HTTP)
.project("admin")
.username("admin")
.password("nova")
.perspective(OpenstackAuth.Perspective.PUBLIC)
.build();
OpenstackNode node = DefaultOpenstackNode.builder()
.hostname("controller")
.type(OpenstackNode.NodeType.CONTROLLER)
.state(NodeState.INIT)
.managementIp(IpAddress.valueOf("172.16.130.10"))
.endpoint("keystone-end-point-url")
.authentication(auth)
.build();
ObjectNode nodeJson = openstackNodeCodec.encode(node, context);
assertThat(nodeJson, matchesOpenstackNode(node));
}
/**
* Tests the openstack controller node decoding.
*/
@Test
public void testOpenstackControllerNodeDecode() throws IOException {
OpenstackNode node = getOpenstackNode("OpenstackControllerNode.json");
assertThat(node.hostname(), is("controller"));
assertThat(node.type().name(), is("CONTROLLER"));
assertThat(node.managementIp().toString(), is("172.16.130.10"));
assertThat(node.endpoint(), is("keystone-end-point-url"));
OpenstackAuth auth = node.authentication();
assertThat(auth.version(), is("v2.0"));
assertThat(auth.protocol(), is(OpenstackAuth.Protocol.HTTP));
assertThat(auth.username(), is("admin"));
assertThat(auth.password(), is("nova"));
assertThat(auth.project(), is("admin"));
assertThat(auth.perspective(), is(OpenstackAuth.Perspective.PUBLIC));
}
/**
* Reads in an openstack node from the given resource and decodes it.
*
* @param resourceName resource to use to read the JSON for the rule
* @return decoded openstack node
* @throws IOException if processing the resource fails
*/
private OpenstackNode getOpenstackNode(String resourceName) throws IOException {
InputStream jsonStream = OpenstackNodeCodecTest.class.getResourceAsStream(resourceName);
JsonNode json = context.mapper().readTree(jsonStream);
MatcherAssert.assertThat(json, notNullValue());
OpenstackNode node = openstackNodeCodec.decode((ObjectNode) json, context);
assertThat(node, notNullValue());
return node;
}
/**
* Mock codec context for use in codec unit tests.
*/
private class MockCodecContext implements CodecContext {
private final ObjectMapper mapper = new ObjectMapper();
private final CodecManager manager = new CodecManager();
private final Map<Class<?>, Object> services = new HashMap<>();
/**
* Constructs a new mock codec context.
*/
public MockCodecContext() {
manager.activate();
}
@Override
public ObjectMapper mapper() {
return mapper;
}
@Override
@SuppressWarnings("unchecked")
public <T> JsonCodec<T> codec(Class<T> entityClass) {
if (entityClass == OpenstackPhyInterface.class) {
return (JsonCodec<T>) openstackPhyIntfJsonCodec;
}
if (entityClass == ControllerInfo.class) {
return (JsonCodec<T>) openstackControllerJsonCodec;
}
if (entityClass == OpenstackAuth.class) {
return (JsonCodec<T>) openstackAuthJsonCodec;
}
if (entityClass == OpenstackSshAuth.class) {
return (JsonCodec<T>) openstackSshAuthJsonCodec;
}
if (entityClass == DpdkConfig.class) {
return (JsonCodec<T>) dpdkConfigJsonCodec;
}
if (entityClass == DpdkInterface.class) {
return (JsonCodec<T>) dpdkInterfaceJsonCodec;
}
return manager.getCodec(entityClass);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getService(Class<T> serviceClass) {
return (T) services.get(serviceClass);
}
// for registering mock services
public <T> void registerService(Class<T> serviceClass, T impl) {
services.put(serviceClass, impl);
}
}
}