/*
* Copyright (c) 2014 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.coordinator.client.service;
import static org.junit.Assert.fail;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.coordinator.client.model.Constants;
import com.emc.storageos.coordinator.client.service.impl.CoordinatorClientImpl;
import com.emc.storageos.coordinator.client.service.impl.CoordinatorClientInetAddressMap;
import com.emc.storageos.coordinator.client.service.impl.DualInetAddress;
import com.emc.storageos.coordinator.common.impl.ConfigurationImpl;
public class CoordinatorClientInetAddressMapTest extends CoordinatorTestBase {
private static final Logger _logger = LoggerFactory
.getLogger(CoordinatorClientInetAddressMapTest.class);
private static final String[] nodes = new String[] { "vipr1", "vipr2", "vipr3" };
private static final String[] ip4 = new String[] { "10.10.10.1", "10.10.10.2", "10.10.10.3" };
private static final String[] ip6 = new String[] { "FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
"fe80::250:56ff:fe8e:4976", "ABCD:EF01:2345:6789:ABCD:EF01:2345:6789" };
private static final String[] external_nodes = new String[] { "data1", "data2", "data3" };
private static final String external_ipv4 = "10.10.10.110";
private static final String external_ipv6 = "fe80::226:2dff:fefa:5ff";
private DualInetAddress external_dualinetaddress;
private CoordinatorClientImpl client;
private CoordinatorClientInetAddressMap nodeMap = new CoordinatorClientInetAddressMap();
@Before
public void setUp() throws Exception {
// init the map with defaults
Map<String, DualInetAddress> controllerNodeMap = new ConcurrentHashMap<String, DualInetAddress>();
Map<String, DualInetAddress> externalNodeMap = new ConcurrentHashMap<String, DualInetAddress>();
for (int i = 0; i < nodes.length; i++) {
controllerNodeMap.put(nodes[i], DualInetAddress.fromAddresses(ip4[i], ip6[i]));
}
// one external node - 10.10.10.110/fe80::226:2dff:fefa:5ff
external_dualinetaddress = DualInetAddress.fromAddresses(external_ipv4, external_ipv6);
externalNodeMap.put(external_nodes[0], external_dualinetaddress);
// set to node map
// *** assume this node[0]
nodeMap.setNodeId(nodes[0]);
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(ip4[0], ip6[0]));
nodeMap.setControllerNodeIPLookupMap(controllerNodeMap);
nodeMap.setExternalInetAddressLookupMap(externalNodeMap);
client = (CoordinatorClientImpl) connectClient();
client.setInetAddessLookupMap(nodeMap);
nodeMap.setCoordinatorClient(client);
client.start();
}
/**
* Connects to test coordinator
*
* @return connected client
* @throws Exception
*/
protected static CoordinatorClient connectClient() throws Exception {
CoordinatorClientImpl client = new CoordinatorClientImpl();
client.setZkConnection(createConnection(10 * 1000));
return client;
}
/**
* Set node info to zk.
*/
public void setNodeDualInetAddressInfo(String nodeId, String address) {
try {
ConfigurationImpl cfg = new ConfigurationImpl();
cfg.setId(nodeId);
cfg.setKind(Constants.NODE_DUALINETADDR_CONFIG);
cfg.setConfig(Constants.CONFIG_DUAL_INETADDRESSES, address);
client.persistServiceConfiguration(cfg);
} catch (Exception e) {
_logger.error("Failed to set node DualInetAddress info", e);
fail(e.getMessage());
}
}
@After
public void tearDown() throws Exception {
}
/**
* Test getConnectableAddress(node_id), given a nodeId. Node will be looked up in the controller
* map, external node map, then the zk configurations. Not connectable exception will be thrown
* if no connectable ip is found.
*
* @see DualInetAddress getConnectableAddress(String host)
*/
@Test
public void testGetConnectableAddressWithId() throws Exception {
// *** assume this node[0]
nodeMap.setNodeId(nodes[0]);
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(ip4[0], ip6[0]));
// 1. test controller nodes, this should pass lookup
String nodeId = nodes[1];
String ip = nodeMap.getConnectableInternalAddress(nodeId);
Assert.assertNotNull(ip);
Assert.assertTrue(ip.compareTo(ip4[1]) == 0);
// 2. test external node in the map, this should pass
nodeId = external_nodes[0];
ip = nodeMap.getConnectableInternalAddress(nodeId);
Assert.assertNotNull(ip);
Assert.assertTrue(ip.compareTo(external_dualinetaddress.getInet4()) == 0);
// 3. test nodes not known, in zk -
// create the external node not in the map and send to zk
ip = "10.10.10.111";// ipv4
nodeId = external_nodes[2];// date3
setNodeDualInetAddressInfo(nodeId, ip);
// now look it up in the map, should pass
String foundIp = nodeMap.getConnectableInternalAddress(nodeId);
Assert.assertNotNull(ip);
Assert.assertTrue(foundIp.compareTo(ip) == 0);
// 4. If local node is ipv6 - this should fail, notconnectable exception
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(null, ip6[0]));
boolean found = true;
try {
foundIp = nodeMap.getConnectableInternalAddress(nodeId);
} catch (Exception ex) {
found = false;
}
Assert.assertFalse(found);
// 5. Given remote server dual stack, local node ipv6
// should return v6 only
ip = "10.10.10.112,fe80:0:ff:ffff:ffff:ffff:ffff:ffff";// ipv4/ipv6
nodeId = external_nodes[1];// date3
setNodeDualInetAddressInfo(nodeId, ip);
// now look it up - should return ipv6
foundIp = nodeMap.getConnectableInternalAddress(nodeId);
Assert.assertNotNull(ip);
Assert.assertTrue(foundIp.compareToIgnoreCase("fe80:0:ff:ffff:ffff:ffff:ffff:ffff") == 0);
}
/**
* Test expandURI, @see CoordinatorClientInetAddressMap.expandURI(URI Uri). Should ba able to
* find the host from the uri and resolve with ip addresses. If not in the controller map nor
* external map, should look up in zk; Fails if still not able to find, notConnectable exception
* will occur.
*/
@Test
public void testExpandURI() throws Exception {
// *** assume this node[0], dual stack
nodeMap.setNodeId(nodes[0]);
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(ip4[0], ip6[0]));
// 1. controller nodes should resolve/expand
String uriString = "http://" + nodes[0] + ":9998/upgrade/internal";
URI uri = URI.create(uriString);
URI newUri = nodeMap.expandURI(uri);
Assert.assertNotNull(newUri);
// local dualstack, remote dualstack, should return ipv4
Assert.assertTrue(newUri.getHost().compareTo(ip4[0]) == 0);
// 2. external known node, should resolve/expand
uriString = "http://" + external_nodes[0] + ":9091/upgrade/internal";
uri = URI.create(uriString);
newUri = nodeMap.expandURI(uri);
Assert.assertNotNull(newUri);
// should return ipv4
Assert.assertTrue(newUri.getHost().compareTo(external_ipv4) == 0);
// 3. local ipv6 only, should return ipv6
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(null, ip6[0]));
uriString = "http://" + external_nodes[0] + ":9091/upgrade/internal";
uri = URI.create(uriString);
newUri = nodeMap.expandURI(uri);
Assert.assertNotNull(newUri);
// should return ipv6
Assert.assertTrue(newUri.getHost().compareTo("[" + external_ipv6 + "]") == 0);
// 4.local dual stack, external unknown, throw exception, return same uri
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(ip4[0], ip6[0]));
uriString = "http://" + external_nodes[1] + ":9091/upgrade/internal";
uri = URI.create(uriString);
newUri = nodeMap.expandURI(uri);
String host = newUri.getHost();
Assert.assertTrue(host.compareToIgnoreCase(external_nodes[1]) == 0);
// now if I persist data2 into zk, expandURi should pass
String ip = "10.10.10.115";// ipv4
String nodeId = external_nodes[1];// date2
setNodeDualInetAddressInfo(nodeId, ip);
uriString = "http://" + external_nodes[1] + ":9091/upgrade/internal";
uri = URI.create(uriString);
newUri = nodeMap.expandURI(uri);
host = newUri.getHost();
Assert.assertFalse(host.compareToIgnoreCase(external_nodes[1]) == 0);
Assert.assertTrue(host.compareTo(ip) == 0);
// 5. data service
ip = "10.10.10.115";// ipv4
nodeId = "dataservice-10-10-10-115";// date2
setNodeDualInetAddressInfo(nodeId, ip);
uriString = "http://dataservice-10-10-10-115:9091/";
uri = URI.create(uriString);
newUri = nodeMap.expandURI(uri);
host = newUri.getHost();
Assert.assertNotNull(host);
Assert.assertTrue(host.compareTo(ip) == 0);
}
/**
* Test get remote server IP address based on local ip.
*
* @throws UnknownHostException
*/
@Test
public void testGetExternalConnectableAddress() throws UnknownHostException {
nodeMap.setNodeId(nodes[0]);
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(ip4[0], ip6[0]));
String external_ip = "10.10.10.200";// remote node
String remote = nodeMap.getExternalConnectableAddress(external_ip);
Assert.assertNotNull(remote);
Assert.assertTrue(remote.compareTo(external_ip) == 0);
external_ip = "emc.com";// remote node
remote = nodeMap.getExternalConnectableAddress(external_ip);
// Above should return ipv4
Assert.assertNotNull(remote);
Assert.assertNotNull(DualInetAddress.fromAddresses(remote, null));
// test empty or "0.0.0.0"
external_ip = "0.0.0.0";// remote node
remote = nodeMap.getExternalConnectableAddress(external_ip);
// Above should return ipv4
Assert.assertNotNull(remote);
Assert.assertNotNull(DualInetAddress.fromAddresses(remote, null));
external_ip = " ";// remote node
remote = nodeMap.getExternalConnectableAddress(external_ip);
// Above should return null
Assert.assertNull(remote);
// local v6 only, remote v4, fail
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(null, ip6[0]));
external_ip = "10.10.10.200";// remote node
boolean found = true;
try {
remote = nodeMap.getExternalConnectableAddress(external_ip);
} catch (Exception ex) {
found = false;
}
Assert.assertFalse(found);
// both ipv6 return v6
// local v6 only, remote v4, fail
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(null, ip6[0]));
external_ip = ip6[1];// remote node
remote = nodeMap.getExternalConnectableAddress(external_ip);
Assert.assertNotNull(remote);
Assert.assertTrue(remote.compareTo(external_ip) == 0);
}
/**
* Test get local server IP address based on remote ip address.
*
* @throws UnknownHostException
*/
@Test
public void testGetLocalConnectableAddress() throws UnknownHostException {
nodeMap.setNodeId(nodes[0]);
nodeMap.setDualInetAddress(DualInetAddress.fromAddresses(ip4[0], ip6[0]));
String external_ip = "10.10.10.200";// remote node
String local = nodeMap.getLocalConnectableAddress(external_ip);
Assert.assertNotNull(local);
Assert.assertTrue(local.compareTo(ip4[0]) == 0);
external_ip = "emc.com";// remote node
local = nodeMap.getLocalConnectableAddress(external_ip);
// Above should return ipv4
Assert.assertNotNull(local);
Assert.assertNotNull(DualInetAddress.fromAddresses(local, null));
// test empty or "0.0.0.0"
external_ip = "0.0.0.0";// remote node
local = nodeMap.getLocalConnectableAddress(external_ip);
// Above should return ipv4
Assert.assertNotNull(local);
Assert.assertNotNull(DualInetAddress.fromAddresses(local, null));
external_ip = "";// remote node
local = nodeMap.getExternalConnectableAddress(external_ip);
// Above should return null
Assert.assertNull(local);
// remote v6, local should return v6
external_ip = ip6[1];// remote node
local = nodeMap.getLocalConnectableAddress(external_ip);
Assert.assertNotNull(local);
Assert.assertNotNull(DualInetAddress.fromAddresses(null, local));
Assert.assertTrue(local.compareTo(ip6[0]) == 0);
}
}