blob: 9fad51cdfb21c1887b949e6b67701a7b6a38c450 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Laboratory
*
* 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.ui.impl.topo.model;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.mastership.MastershipService;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultHost;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.host.HostService;
import org.onosproject.net.host.HostServiceAdapter;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.link.LinkServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.region.DefaultRegion;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionId;
import org.onosproject.net.region.RegionListener;
import org.onosproject.net.region.RegionService;
import org.onosproject.ui.impl.AbstractUiImplTest;
import org.onosproject.ui.model.ServiceBundle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.onosproject.cluster.NodeId.nodeId;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.HostId.hostId;
import static org.onosproject.net.PortNumber.portNumber;
/**
* Base class for model test classes.
*/
abstract class AbstractTopoModelTest extends AbstractUiImplTest {
/*
Our mock environment:
Three controllers: C1, C2, C3
Nine devices: D1 .. D9
D4 ---+ +--- D7
| |
D5 --- D1 --- D2 --- D3 --- D8
| |
D6 ---+ +--- D9
Twelve hosts (two per D4 ... D9) H4a, H4b, H5a, H5b, ...
Regions:
R1 : D1, D2, D3
R2 : D4, D5, D6
R3 : D7, D8, D9
Mastership:
C1 : D1, D2, D3
C2 : D4, D5, D6
C3 : D7, D8, D9
Roles: (backups)
C1 -> C2, C3
C2 -> C1, C3
C3 -> C1, C2
*/
protected static final String C1 = "C1";
protected static final String C2 = "C2";
protected static final String C3 = "C3";
protected static final NodeId CNID_1 = nodeId(C1);
protected static final NodeId CNID_2 = nodeId(C2);
protected static final NodeId CNID_3 = nodeId(C3);
protected static final ControllerNode CNODE_1 = cnode(CNID_1, "10.0.0.1");
protected static final ControllerNode CNODE_2 = cnode(CNID_2, "10.0.0.2");
protected static final ControllerNode CNODE_3 = cnode(CNID_3, "10.0.0.3");
protected static final String R1 = "R1";
protected static final String R2 = "R2";
protected static final String R3 = "R3";
protected static final Set<NodeId> SET_C1 = ImmutableSet.of(CNID_1);
protected static final Set<NodeId> SET_C2 = ImmutableSet.of(CNID_2);
protected static final Set<NodeId> SET_C3 = ImmutableSet.of(CNID_3);
protected static final Region REGION_1 =
region(R1, Region.Type.METRO, ImmutableList.of(SET_C1, SET_C2));
protected static final Region REGION_2 =
region(R2, Region.Type.CAMPUS, ImmutableList.of(SET_C2, SET_C1));
protected static final Region REGION_3 =
region(R3, Region.Type.CAMPUS, ImmutableList.of(SET_C3, SET_C1));
protected static final Set<Region> REGION_SET =
ImmutableSet.of(REGION_1, REGION_2, REGION_3);
protected static final String D1 = "d1";
protected static final String D2 = "d2";
protected static final String D3 = "d3";
protected static final String D4 = "d4";
protected static final String D5 = "d5";
protected static final String D6 = "d6";
protected static final String D7 = "d7";
protected static final String D8 = "d8";
protected static final String D9 = "d9";
protected static final String MFR = "Mfr";
protected static final String HW = "h/w";
protected static final String SW = "s/w";
protected static final String SERIAL = "ser123";
protected static final DeviceId DEVID_1 = deviceId(D1);
protected static final DeviceId DEVID_2 = deviceId(D2);
protected static final DeviceId DEVID_3 = deviceId(D3);
protected static final DeviceId DEVID_4 = deviceId(D4);
protected static final DeviceId DEVID_5 = deviceId(D5);
protected static final DeviceId DEVID_6 = deviceId(D6);
protected static final DeviceId DEVID_7 = deviceId(D7);
protected static final DeviceId DEVID_8 = deviceId(D8);
protected static final DeviceId DEVID_9 = deviceId(D9);
protected static final Device DEV_1 = device(D1);
protected static final Device DEV_2 = device(D2);
protected static final Device DEV_3 = device(D3);
protected static final Device DEV_4 = device(D4);
protected static final Device DEV_5 = device(D5);
protected static final Device DEV_6 = device(D6);
protected static final Device DEV_7 = device(D7);
protected static final Device DEV_8 = device(D8);
protected static final Device DEV_9 = device(D9);
protected static final List<Device> ALL_DEVS =
ImmutableList.of(
DEV_1, DEV_2, DEV_3,
DEV_4, DEV_5, DEV_6,
DEV_7, DEV_8, DEV_9
);
private static final Set<DeviceId> DEVS_TRUNK =
ImmutableSet.of(DEVID_1, DEVID_2, DEVID_3);
private static final Set<DeviceId> DEVS_LEFT =
ImmutableSet.of(DEVID_4, DEVID_5, DEVID_6);
private static final Set<DeviceId> DEVS_RIGHT =
ImmutableSet.of(DEVID_7, DEVID_8, DEVID_9);
private static final String[][] LINK_CONNECT_DATA = {
{D1, "12", D2, "21"},
{D2, "23", D3, "32"},
{D4, "41", D1, "14"},
{D5, "51", D1, "15"},
{D6, "61", D1, "16"},
{D7, "73", D3, "37"},
{D8, "83", D3, "38"},
{D9, "93", D3, "39"},
};
private static final String HOST_MAC_PREFIX = "aa:00:00:00:00:";
/**
* Returns IP address instance for given string.
*
* @param s string
* @return IP address
*/
protected static IpAddress ip(String s) {
return IpAddress.valueOf(s);
}
/**
* Returns controller node instance for given ID and IP.
*
* @param id identifier
* @param ip IP address
* @return controller node instance
*/
protected static ControllerNode cnode(NodeId id, String ip) {
return new DefaultControllerNode(id, ip(ip));
}
/**
* Returns a region instance with specified parameters.
*
* @param id region id
* @param type region type
* @param masters ordered list of master sets
* @return region instance
*/
protected static Region region(String id, Region.Type type,
List<Set<NodeId>> masters) {
return new DefaultRegion(RegionId.regionId(id), "Region-" + id,
type, masters);
}
/**
* Returns device with given ID.
*
* @param id device ID
* @return device instance
*/
protected static Device device(String id) {
return new DefaultDevice(ProviderId.NONE, deviceId(id),
Device.Type.SWITCH, MFR, HW, SW, SERIAL, null);
}
/**
* Returns canned results.
* <p>
* At some future point, we may make this "programmable", so that
* its state can be changed over the course of a unit test.
*/
protected static final ServiceBundle MOCK_SERVICES =
new ServiceBundle() {
@Override
public ClusterService cluster() {
return MOCK_CLUSTER;
}
@Override
public MastershipService mastership() {
return MOCK_MASTER;
}
@Override
public RegionService region() {
return MOCK_REGION;
}
@Override
public DeviceService device() {
return MOCK_DEVICE;
}
@Override
public LinkService link() {
return MOCK_LINK;
}
@Override
public HostService host() {
return MOCK_HOST;
}
@Override
public IntentService intent() {
return null;
}
@Override
public FlowRuleService flow() {
return null;
}
};
private static final ClusterService MOCK_CLUSTER = new MockClusterService();
private static final MastershipService MOCK_MASTER = new MockMasterService();
private static final RegionService MOCK_REGION = new MockRegionService();
private static final DeviceService MOCK_DEVICE = new MockDeviceService();
private static final LinkService MOCK_LINK = new MockLinkService();
private static final HostService MOCK_HOST = new MockHostService();
private static class MockClusterService extends ClusterServiceAdapter {
private final Map<NodeId, ControllerNode> nodes = new HashMap<>();
private final Map<NodeId, ControllerNode.State> states = new HashMap<>();
MockClusterService() {
nodes.put(CNODE_1.id(), CNODE_1);
nodes.put(CNODE_2.id(), CNODE_2);
nodes.put(CNODE_3.id(), CNODE_3);
states.put(CNODE_1.id(), ControllerNode.State.READY);
states.put(CNODE_2.id(), ControllerNode.State.ACTIVE);
states.put(CNODE_3.id(), ControllerNode.State.ACTIVE);
}
@Override
public Set<ControllerNode> getNodes() {
return ImmutableSet.copyOf(nodes.values());
}
@Override
public ControllerNode getNode(NodeId nodeId) {
return nodes.get(nodeId);
}
@Override
public ControllerNode.State getState(NodeId nodeId) {
return states.get(nodeId);
}
}
private static class MockMasterService extends MastershipServiceAdapter {
private final Map<NodeId, Set<DeviceId>> masterOf = new HashMap<>();
MockMasterService() {
masterOf.put(CNODE_1.id(), DEVS_TRUNK);
masterOf.put(CNODE_2.id(), DEVS_LEFT);
masterOf.put(CNODE_3.id(), DEVS_RIGHT);
}
@Override
public NodeId getMasterFor(DeviceId deviceId) {
if (DEVS_TRUNK.contains(deviceId)) {
return CNID_1;
}
if (DEVS_LEFT.contains(deviceId)) {
return CNID_2;
}
if (DEVS_RIGHT.contains(deviceId)) {
return CNID_3;
}
return null;
}
@Override
public Set<DeviceId> getDevicesOf(NodeId nodeId) {
return masterOf.get(nodeId);
}
@Override
public RoleInfo getNodesFor(DeviceId deviceId) {
NodeId master = null;
List<NodeId> backups = new ArrayList<>();
if (DEVS_TRUNK.contains(deviceId)) {
master = CNID_1;
backups.add(CNID_2);
backups.add(CNID_3);
} else if (DEVS_LEFT.contains(deviceId)) {
master = CNID_2;
backups.add(CNID_1);
backups.add(CNID_3);
} else if (DEVS_RIGHT.contains(deviceId)) {
master = CNID_3;
backups.add(CNID_1);
backups.add(CNID_2);
}
return new RoleInfo(master, backups);
}
}
// TODO: consider implementing RegionServiceAdapter and extending that here
private static class MockRegionService implements RegionService {
private final Map<RegionId, Region> lookup = new HashMap<>();
MockRegionService() {
lookup.put(REGION_1.id(), REGION_1);
lookup.put(REGION_2.id(), REGION_2);
lookup.put(REGION_3.id(), REGION_3);
}
@Override
public Set<Region> getRegions() {
return REGION_SET;
}
@Override
public Region getRegion(RegionId regionId) {
return lookup.get(regionId);
}
@Override
public Region getRegionForDevice(DeviceId deviceId) {
if (DEVS_TRUNK.contains(deviceId)) {
return REGION_1;
}
if (DEVS_LEFT.contains(deviceId)) {
return REGION_2;
}
if (DEVS_RIGHT.contains(deviceId)) {
return REGION_3;
}
return null;
}
@Override
public Set<DeviceId> getRegionDevices(RegionId regionId) {
if (REGION_1.id().equals(regionId)) {
return DEVS_TRUNK;
}
if (REGION_2.id().equals(regionId)) {
return DEVS_LEFT;
}
if (REGION_3.id().equals(regionId)) {
return DEVS_RIGHT;
}
return Collections.emptySet();
}
@Override
public void addListener(RegionListener listener) {
}
@Override
public void removeListener(RegionListener listener) {
}
}
private static class MockDeviceService extends DeviceServiceAdapter {
private final Map<DeviceId, Device> devices = new HashMap<>();
MockDeviceService() {
for (Device dev : ALL_DEVS) {
devices.put(dev.id(), dev);
}
}
@Override
public int getDeviceCount() {
return devices.size();
}
@Override
public Iterable<Device> getDevices() {
return ImmutableList.copyOf(devices.values());
}
@Override
public Device getDevice(DeviceId deviceId) {
return devices.get(deviceId);
}
}
/**
* Synthesizes a pair of unidirectional links between two devices. The
* string array should be of the form:
* <pre>
* { "device-A-id", "device-A-port", "device-B-id", "device-B-port" }
* </pre>
*
* @param linkPairData device ids and ports
* @return pair of synthesized links
*/
protected static List<Link> makeLinkPair(String[] linkPairData) {
DeviceId devA = deviceId(linkPairData[0]);
PortNumber portA = portNumber(Long.valueOf(linkPairData[1]));
DeviceId devB = deviceId(linkPairData[2]);
PortNumber portB = portNumber(Long.valueOf(linkPairData[3]));
Link linkA = DefaultLink.builder()
.providerId(ProviderId.NONE)
.type(Link.Type.DIRECT)
.src(new ConnectPoint(devA, portA))
.dst(new ConnectPoint(devB, portB))
.build();
Link linkB = DefaultLink.builder()
.providerId(ProviderId.NONE)
.type(Link.Type.DIRECT)
.src(new ConnectPoint(devB, portB))
.dst(new ConnectPoint(devA, portA))
.build();
return ImmutableList.of(linkA, linkB);
}
private static class MockLinkService extends LinkServiceAdapter {
private final Set<Link> links = new HashSet<>();
MockLinkService() {
for (String[] linkPair : LINK_CONNECT_DATA) {
links.addAll(makeLinkPair(linkPair));
}
}
@Override
public int getLinkCount() {
return links.size();
}
@Override
public Iterable<Link> getLinks() {
return ImmutableSet.copyOf(links);
}
// TODO: possibly fill out other methods if we find the model uses them
}
private static class MockHostService extends HostServiceAdapter {
private final Map<HostId, Host> hosts = new HashMap<>();
MockHostService() {
for (Device d : ALL_DEVS) {
// two hosts per device
createHosts(hosts, d);
}
}
private void createHosts(Map<HostId, Host> hosts, Device d) {
DeviceId deviceId = d.id();
String devNum = deviceId.toString().substring(1);
String ha = devNum + "a";
String hb = devNum + "b";
MacAddress macA = MacAddress.valueOf(HOST_MAC_PREFIX + ha);
MacAddress macB = MacAddress.valueOf(HOST_MAC_PREFIX + hb);
HostId hostA = hostId(String.format("%s/-1", macA));
HostId hostB = hostId(String.format("%s/-1", macB));
PortNumber portA = portNumber(101);
PortNumber portB = portNumber(102);
HostLocation locA = new HostLocation(deviceId, portA, 0);
HostLocation locB = new HostLocation(deviceId, portB, 0);
IpAddress ipA = ip("10." + devNum + ".0.1");
IpAddress ipB = ip("10." + devNum + ".0.2");
Host host = new DefaultHost(ProviderId.NONE,
hostA, macA, VlanId.NONE, locA,
ImmutableSet.of(ipA));
hosts.put(hostA, host);
host = new DefaultHost(ProviderId.NONE,
hostB, macB, VlanId.NONE, locB,
ImmutableSet.of(ipB));
hosts.put(hostB, host);
}
@Override
public int getHostCount() {
return hosts.size();
}
@Override
public Iterable<Host> getHosts() {
return ImmutableSet.copyOf(hosts.values());
}
@Override
public Host getHost(HostId hostId) {
return hosts.get(hostId);
}
// TODO: possibly fill out other methods, should the model require them
}
}