package org.openstack.atlas.adapter.itest;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openstack.atlas.adapter.exceptions.InsufficientRequestException;
import org.openstack.atlas.adapter.helpers.ResourceTranslator;
import org.openstack.atlas.adapter.helpers.ZeusNodePriorityContainer;
import org.openstack.atlas.service.domain.entities.*;
import org.openstack.atlas.service.domain.pojos.ZeusSslTermination;
import org.openstack.atlas.util.ca.zeus.ZeusCrtFile;
import org.openstack.atlas.util.ip.exception.IPStringConversionException;
import org.rackspace.stingray.client.StingrayRestClient;
import org.rackspace.stingray.client.bandwidth.Bandwidth;
import org.rackspace.stingray.client.bandwidth.BandwidthBasic;
import org.rackspace.stingray.client.exception.StingrayRestClientException;
import org.rackspace.stingray.client.exception.StingrayRestClientObjectNotFoundException;
import org.rackspace.stingray.client.monitor.Monitor;
import org.rackspace.stingray.client.monitor.MonitorHttp;
import org.rackspace.stingray.client.pool.Pool;
import org.rackspace.stingray.client.pool.PoolNodeWeight;
import org.rackspace.stingray.client.protection.Protection;
import org.rackspace.stingray.client.protection.ProtectionAccessRestriction;
import org.rackspace.stingray.client.protection.ProtectionConnectionLimiting;
import org.rackspace.stingray.client.traffic.ip.TrafficIp;
import org.rackspace.stingray.client.virtualserver.VirtualServer;
import org.rackspace.stingray.client.virtualserver.VirtualServerBasic;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import static org.openstack.atlas.service.domain.entities.AccessListType.ALLOW;
import static org.openstack.atlas.service.domain.entities.AccessListType.DENY;
import static org.openstack.atlas.service.domain.entities.SessionPersistence.HTTP_COOKIE;
public class FullConfigITest extends STMTestBase {
static StingrayRestClient client;
Node n1;
Node n2;
Node n3;
/**
* Have to run in order, some tests depend on others for values in STM...
*/
@BeforeClass
public static void setupClass() throws InterruptedException {
Thread.sleep(SLEEP_TIME_BETWEEN_TESTS);
setupIvars();
client = stmClient;
}
@AfterClass
public static void tearDownClass() {
teardownEverything();
}
@Test
public void createFullyConfiguredLoadBalancer() {
try {
stmAdapter.createLoadBalancer(config, buildHydratedLb());
Thread.sleep(3000);
verifyVS(lb);
verifyPool(lb);
verifyMonitor(lb);
verifyProtection(lb);
verifyVips(lb);
} catch (Exception e) {
e.printStackTrace();
removeLoadBalancer();
Assert.fail(e.getMessage());
}
}
@Test
public void updateFullyConfiguredLoadBalancer() {
try {
buildHydratedLb();
LoadBalancer nlb = new LoadBalancer();
VirtualIp v = new VirtualIp();
v.setIpAddress("10.3.5.6");
v.setId(12);
LoadBalancerJoinVip jv = new LoadBalancerJoinVip(80, lb, v);
lb.getLoadBalancerJoinVipSet().add(jv);
nlb.setLoadBalancerJoinVipSet(lb.getLoadBalancerJoinVipSet());
UserPages up = new UserPages();
up.setErrorpage("iError");
nlb.setUserPages(up);
lb.setUserPages(up);
HealthMonitor mon = new HealthMonitor();
mon.setType(HealthMonitorType.HTTP);
mon.setStatusRegex("202");
mon.setBodyRegex("");
mon.setAttemptsBeforeDeactivation(4);
mon.setDelay(3);
mon.setPath("/");
mon.setTimeout(2);
mon.setHostHeader("");
nlb.setHealthMonitor(mon);
lb.setHealthMonitor(mon);
nlb.setSessionPersistence(HTTP_COOKIE);
lb.setSessionPersistence(HTTP_COOKIE);
AccessList al = new AccessList();
al.setIpAddress("10.1.1.76");
al.setType(AccessListType.ALLOW);
Set<AccessList> all = new HashSet<AccessList>();
all.add(al);
nlb.setAccessLists(all);
lb.setAccessLists(all);
lb.getConnectionLimit().setMaxConnectionRate(5);
lb.getConnectionLimit().setMinConnections(3);
lb.getConnectionLimit().setRateInterval(31);
nlb.setConnectionLimit(lb.getConnectionLimit());
nlb.setHalfClosed(false);
lb.setHalfClosed(false);
nlb.setTimeout(35);
lb.setTimeout(35);
lb.setConnectionLogging(true);
lb.setContentCaching(true);
SslTermination sslTermination = new SslTermination();
sslTermination.setSecureTrafficOnly(false);
sslTermination.setEnabled(true);
sslTermination.setSecurePort(StmTestConstants.LB_SECURE_PORT);
sslTermination.setCertificate(StmTestConstants.SSL_CERT);
sslTermination.setPrivatekey(StmTestConstants.SSL_KEY);
ZeusCrtFile zeusCertFile = new ZeusCrtFile();
zeusCertFile.setPublic_cert(StmTestConstants.SSL_CERT);
zeusCertFile.setPrivate_key(StmTestConstants.SSL_KEY);
ZeusSslTermination zeusSslTermination = new ZeusSslTermination();
zeusSslTermination.setCertIntermediateCert(StmTestConstants.SSL_CERT);
zeusSslTermination.setSslTermination(sslTermination);
stmAdapter.updateLoadBalancer(config, lb, nlb, up);
lb.setSslTermination(zeusSslTermination.getSslTermination());
stmAdapter.updateSslTermination(config, lb, zeusSslTermination, up);
verifySsltermination(lb);
Thread.sleep(3000);
verifyVS(lb);
verifyPool(lb);
verifyMonitor(lb);
verifyProtection(lb);
verifyVips(lb);
} catch (Exception e) {
e.printStackTrace();
removeLoadBalancer();
Assert.fail(e.getMessage());
}
}
@Test
public void updateFullyConfiguredLoadBalancerWithHealthMonitorRollbacks() throws StingrayRestClientException, IOException, StingrayRestClientObjectNotFoundException, InsufficientRequestException, IPStringConversionException {
LoadBalancer clb = null;
try {
LoadBalancer nlb = new LoadBalancer();
clb = new LoadBalancer();
clb.setHealthMonitor(lb.getHealthMonitor());
HealthMonitor mon = new HealthMonitor();
mon.setType(HealthMonitorType.HTTP);
mon.setStatusRegex("207");
mon.setBodyRegex("[0-9]");
mon.setAttemptsBeforeDeactivation(1);
mon.setDelay(6);
mon.setPath("circle");
mon.setTimeout(3);
mon.setHostHeader("header");
nlb.setHealthMonitor(mon);
buildHydratedLb();
lb.setSslTermination(null);
lb.setHealthMonitor(mon);
stmAdapter.updateLoadBalancer(config, lb, nlb, null);
Assert.fail("Should have failed to update");
} catch (Exception e) {
verifyMonitor(clb);
}
}
@Test
public void updateFullyConfiguredLoadBalancerWithProtectionrollbacks() throws StingrayRestClientException, IOException, StingrayRestClientObjectNotFoundException, InsufficientRequestException, IPStringConversionException {
LoadBalancer clb = null;
try {
LoadBalancer nlb = new LoadBalancer();
clb = new LoadBalancer();
clb.setConnectionLimit(lb.getConnectionLimit());
buildHydratedLb();
stmAdapter.updateLoadBalancer(config, lb, lb, null);
lb.getConnectionLimit().setRateInterval(-2);
nlb.setConnectionLimit(lb.getConnectionLimit());
stmAdapter.updateLoadBalancer(config, lb, nlb, null);
Assert.fail("Should have failed to update");
} catch (Exception e) {
verifyProtection(clb);
}
}
@Test
public void updateFullyConfiguredSslLoadBalancerWithSslRollbacks() throws StingrayRestClientException, IPStringConversionException, StingrayRestClientObjectNotFoundException, InsufficientRequestException {
LoadBalancer clb = null;
try {
LoadBalancer nlb = new LoadBalancer();
clb = new LoadBalancer();
SslTermination sslTermination = new SslTermination();
sslTermination.setSecureTrafficOnly(false);
sslTermination.setEnabled(true);
sslTermination.setSecurePort(StmTestConstants.LB_SECURE_PORT);
sslTermination.setCertificate(StmTestConstants.SSL_CERT);
sslTermination.setPrivatekey(StmTestConstants.SSL_KEY);
lb.setSslTermination(sslTermination);
clb.setSslTermination(sslTermination);
clb.setProtocol(lb.getProtocol());
buildHydratedLb();
stmAdapter.updateLoadBalancer(config, lb, lb, null);
lb.getSslTermination().setSecurePort(-10);
nlb.setSslTermination(lb.getSslTermination());
stmAdapter.updateLoadBalancer(config, lb, nlb, null);
Assert.fail("Should have failed to update");
} catch (Exception e) {
verifySsltermination(clb);
}
}
@Test
public void updateFullyConfiguredLoadBalancerWithVirtualIpRollbacks() throws StingrayRestClientException, IPStringConversionException, StingrayRestClientObjectNotFoundException, InsufficientRequestException {
LoadBalancer clb = null;
try {
LoadBalancer nlb = new LoadBalancer();
clb = new LoadBalancer();
buildHydratedLb();
stmAdapter.updateLoadBalancer(config, lb, lb, null);
clb.getLoadBalancerJoinVipSet().addAll(lb.getLoadBalancerJoinVipSet());
lb.getLoadBalancerJoinVipSet().iterator().next().setVirtualIp(new VirtualIp());
nlb.setLoadBalancerJoinVipSet(lb.getLoadBalancerJoinVipSet());
stmAdapter.updateLoadBalancer(config, lb, nlb, null);
Assert.fail("Should have failed to update");
} catch (Exception e) {
verifyVips(clb);
}
}
@Test
public void updateFullyConfiguredLoadBalancerForRateLimitRollbacks() throws StingrayRestClientException, IPStringConversionException, StingrayRestClientObjectNotFoundException, InsufficientRequestException {
try {
buildHydratedLb();
stmAdapter.updateLoadBalancer(config, lb, lb, null);
stmAdapter.updateRateLimit(config, lb, null);
Assert.fail("Should have failed to update");
} catch (Exception e) {
verifyRateLimit(lb);
}
}
@Test
public void updateFullyConfiguredLoadBalancerForErrorPageRollbacks() {
try {
buildHydratedLb();
stmAdapter.updateLoadBalancer(config, lb, lb, null);
stmAdapter.setErrorFile(config, lb, "");
Assert.fail("Should have failed to update");
} catch (Exception e) {
// This check is bad if there are other entries allowed in the user pages. Coded with Error Page only
Assert.assertNull(lb.getUserPages());
}
}
private LoadBalancer buildHydratedLb() {
lb = new LoadBalancer();
lb.setAccountId(TEST_ACCOUNT_ID);
lb.setId(TEST_LOADBALANCER_ID);
lb.setPort(LB_PORT);
lb.setAlgorithm(LoadBalancerAlgorithm.WEIGHTED_ROUND_ROBIN);
lb.setSessionPersistence(HTTP_COOKIE);
lb.setTimeout(99);
lb.setConnectionLogging(true);
lb.setContentCaching(false);
lb.setSessionPersistence(SessionPersistence.HTTP_COOKIE);
lb.setHalfClosed(true);
lb.setProtocol(LoadBalancerProtocol.HTTP);
HealthMonitor monitor = new HealthMonitor();
monitor.setType(HealthMonitorType.CONNECT);
monitor.setDelay(10);
monitor.setTimeout(20);
monitor.setAttemptsBeforeDeactivation(3);
lb.setHealthMonitor(monitor);
ConnectionLimit limit = new ConnectionLimit();
limit.setMaxConnections(50);
limit.setRateInterval(10);
limit.setMaxConnectionRate(10);
limit.setMinConnections(1);
lb.setConnectionLimit(limit);
Set<AccessList> networkItems = new HashSet<AccessList>();
AccessList item1 = new AccessList();
AccessList item2 = new AccessList();
item1.setIpAddress("0.0.0.0/0");
item2.setIpAddress("127.0.0.1");
item1.setType(DENY);
item2.setType(ALLOW);
networkItems.add(item1);
networkItems.add(item2);
lb.setAccessLists(networkItems);
Set<Node> nodes = new HashSet<Node>();
n1 = new Node();
n1.setWeight(1);
n1.setType(NodeType.SECONDARY);
n1.setIpAddress("10.3.3.3");
n1.setCondition(NodeCondition.ENABLED);
n1.setPort(8080);
n1.setStatus(NodeStatus.ONLINE);
nodes.add(n1);
n2 = new Node();
n2.setWeight(3);
n2.setType(NodeType.SECONDARY);
n2.setIpAddress("10.3.3.5");
n2.setCondition(NodeCondition.DISABLED);
n2.setPort(7070);
n2.setStatus(NodeStatus.OFFLINE);
nodes.add(n2);
n3 = new Node();
n3.setWeight(3);
n3.setType(NodeType.SECONDARY);
n3.setIpAddress("10.3.3.9");
n3.setCondition(NodeCondition.DRAINING);
n3.setPort(9090);
n3.setStatus(NodeStatus.OFFLINE);
nodes.add(n3);
lb.setNodes(nodes);
return lb;
}
private VirtualServer verifyVS(LoadBalancer lb) throws InsufficientRequestException, StingrayRestClientException, StingrayRestClientObjectNotFoundException, IOException {
VirtualServer vs = client.getVirtualServer(loadBalancerName());
ResourceTranslator translator = new ResourceTranslator();
Assert.assertNotNull(vs);
Assert.assertEquals(true, vs.getProperties().getBasic().getEnabled());
Assert.assertEquals(lb.getPort(), vs.getProperties().getBasic().getPort());
Assert.assertEquals(poolName(), vs.getProperties().getBasic().getPool());
Assert.assertEquals(lb.isHalfClosed(), vs.getProperties().getTcp().getProxy_close());
Assert.assertEquals(lb.isContentCaching(), vs.getProperties().getWeb_cache().getEnabled());
if (lb.getUserPages() != null) {
Assert.assertEquals(errorFileName(), vs.getProperties().getConnection_errors().getError_file());
File ef = client.getExtraFile(errorFileName());
String content = readFile(ef);
Assert.assertEquals(lb.getUserPages().getErrorpage(), content);
ef.delete();
} else {
Assert.assertEquals("Default", vs.getProperties().getConnection_errors().getError_file());
}
if (lb.getProtocol() == LoadBalancerProtocol.HTTP) {
Assert.assertTrue(vs.getProperties().getBasic().getAdd_x_forwarded_for());
Assert.assertTrue(vs.getProperties().getBasic().getAdd_x_forwarded_proto());
} else {
Assert.assertFalse(vs.getProperties().getBasic().getAdd_x_forwarded_for());
Assert.assertFalse(vs.getProperties().getBasic().getAdd_x_forwarded_proto());
}
Assert.assertEquals(false, vs.getProperties().getBasic().getListen_on_any());
Assert.assertEquals(vs.getProperties().getBasic().getListen_on_traffic_ips(), translator.genGroupNameSet(lb));
Assert.assertEquals(protectionClassName(), vs.getProperties().getBasic().getProtection_class());
return vs;
}
private Pool verifyPool(LoadBalancer lb) throws InsufficientRequestException, StingrayRestClientException, StingrayRestClientObjectNotFoundException {
Pool pool = client.getPool(loadBalancerName());
Assert.assertNotNull(pool);
Assert.assertEquals(1, pool.getProperties().getBasic().getMonitors().size());
Assert.assertEquals(lb.getAlgorithm().name().toLowerCase(), pool.getProperties().getLoad_balancing().getAlgorithm());
Assert.assertEquals(2, pool.getProperties().getBasic().getNodes().size()); // List contains ACTIVE and DRAINING nodes
Assert.assertEquals(1, pool.getProperties().getBasic().getDisabled().size()); // List contains DISABLED nodes
Assert.assertEquals(1, pool.getProperties().getBasic().getDraining().size()); // List contains DRAINING nodes
List<PoolNodeWeight> pws = pool.getProperties().getLoad_balancing().getNode_weighting();
for (PoolNodeWeight pnw : pws) {
Node lbn = lb.getNodes().iterator().next();
if (lbn.getIpAddress().equals(pnw.getNode().split(":")[0])) {
Assert.assertEquals(lbn.getIpAddress() + ":" + lbn.getPort(), pnw.getNode());
Assert.assertEquals(lbn.getWeight(), pnw.getWeight());
}
}
ZeusNodePriorityContainer znpc = new ZeusNodePriorityContainer(lb.getNodes());
Assert.assertEquals(znpc.getPriorityValuesSet(), pool.getProperties().getLoad_balancing().getPriority_values());
Assert.assertEquals(znpc.hasSecondary(), pool.getProperties().getLoad_balancing().getPriority_enabled());
Assert.assertEquals(lb.getTimeout(), pool.getProperties().getConnection().getMax_reply_time());
Assert.assertEquals(new HashSet<String>(Arrays.asList(loadBalancerName())), pool.getProperties().getBasic().getMonitors());
Assert.assertEquals(lb.getSessionPersistence().name(), pool.getProperties().getBasic().getPersistence_class());
Assert.assertEquals("", pool.getProperties().getBasic().getBandwidth_class());
return pool;
}
private Monitor verifyMonitor(LoadBalancer lb) throws InsufficientRequestException, StingrayRestClientException, StingrayRestClientObjectNotFoundException {
Monitor monitor = client.getMonitor(loadBalancerName());
Assert.assertEquals(lb.getHealthMonitor().getType().name(), monitor.getProperties().getBasic().getType().toUpperCase());
Assert.assertEquals(lb.getHealthMonitor().getTimeout(), monitor.getProperties().getBasic().getTimeout());
Assert.assertEquals(lb.getHealthMonitor().getAttemptsBeforeDeactivation(), monitor.getProperties().getBasic().getFailures());
if (lb.getHealthMonitor().getType().equals(HealthMonitorType.HTTP) || lb.getHealthMonitor().equals(HealthMonitorType.HTTPS)) {
MonitorHttp http = monitor.getProperties().getHttp();
HealthMonitor hm = lb.getHealthMonitor();
Assert.assertEquals(hm.getPath(), http.getPath());
Assert.assertEquals(hm.getStatusRegex(), http.getStatus_regex());
Assert.assertEquals(hm.getBodyRegex(), http.getBody_regex());
Assert.assertEquals(hm.getHostHeader(), http.getHost_header());
}
return monitor;
}
private Protection verifyProtection(LoadBalancer lb) throws InsufficientRequestException, StingrayRestClientException, StingrayRestClientObjectNotFoundException {
Protection protection = client.getProtection(loadBalancerName());
if (lb.getAccessLists() != null && !lb.getAccessLists().isEmpty()) {
ProtectionAccessRestriction pal = protection.getProperties().getAccess_restriction();
for (AccessList al : lb.getAccessLists()) {
if (al.getType().equals(AccessListType.ALLOW)) {
Assert.assertTrue(pal.getAllowed().contains(al.getIpAddress()));
} else {
Assert.assertTrue(pal.getBanned().contains(al.getIpAddress()));
}
}
}
if (lb.getConnectionLimit() != null) {
ProtectionConnectionLimiting cl = protection.getProperties().getConnection_limiting();
Assert.assertEquals(lb.getConnectionLimit().getMinConnections(), cl.getMin_connections());
Assert.assertEquals(lb.getConnectionLimit().getMaxConnectionRate(), cl.getMax_connection_rate());
Assert.assertEquals(lb.getConnectionLimit().getMaxConnections(), cl.getMax_1_connections());
Assert.assertEquals(lb.getConnectionLimit().getRateInterval(), cl.getRate_timer());
}
return protection;
}
private void verifyVips(LoadBalancer lb) throws InsufficientRequestException, StingrayRestClientException, StingrayRestClientObjectNotFoundException, IPStringConversionException {
TrafficIp t;
for (LoadBalancerJoinVip jv : lb.getLoadBalancerJoinVipSet()) {
t = client.getTrafficIp(trafficIpGroupName(jv.getVirtualIp()));
Assert.assertTrue(t.getProperties().getBasic().getIpaddresses().contains(jv.getVirtualIp().getIpAddress()));
Assert.assertEquals(true, t.getProperties().getBasic().getEnabled());
Assert.assertTrue(t.getProperties().getBasic().getMachines().contains(config.getFailoverTrafficManagerNames().iterator().next()));
Assert.assertTrue(t.getProperties().getBasic().getMachines().contains(config.getTrafficManagerName()));
}
for (LoadBalancerJoinVip6 jv : lb.getLoadBalancerJoinVip6Set()) {
t = client.getTrafficIp(trafficIpGroupName(jv.getVirtualIp()));
Assert.assertTrue(t.getProperties().getBasic().getIpaddresses().contains(jv.getVirtualIp().getDerivedIpString()));
Assert.assertEquals(true, t.getProperties().getBasic().getEnabled());
Assert.assertTrue(t.getProperties().getBasic().getMachines().contains(config.getFailoverTrafficManagerNames().iterator().next()));
Assert.assertTrue(t.getProperties().getBasic().getMachines().contains(config.getTrafficManagerName()));
}
}
private void verifySsltermination(LoadBalancer lb) throws InsufficientRequestException, StingrayRestClientException, StingrayRestClientObjectNotFoundException, IPStringConversionException {
String svsName = secureLoadBalancerName();
String vsName = loadBalancerName();
VirtualServer createdSecureVs = client.getVirtualServer(svsName);
VirtualServer createdVs = client.getVirtualServer(vsName);
VirtualServerBasic secureBasic = createdSecureVs.getProperties().getBasic();
Assert.assertEquals(StmTestConstants.LB_SECURE_PORT, (int) secureBasic.getPort());
Assert.assertTrue(lb.getProtocol().toString().equalsIgnoreCase(secureBasic.getProtocol().toString()));
Assert.assertEquals(lb.getSslTermination().isEnabled(), secureBasic.getEnabled());
Assert.assertEquals(vsName, secureBasic.getPool().toString());
Assert.assertEquals(true, secureBasic.getSsl_decrypt());
VirtualServerBasic normalBasic = createdVs.getProperties().getBasic();
Assert.assertEquals(StmTestConstants.LB_PORT, (int) normalBasic.getPort());
Assert.assertTrue(lb.getProtocol().toString().equalsIgnoreCase(normalBasic.getProtocol().toString()));
Assert.assertEquals(lb.isSecureOnly(), !normalBasic.getEnabled());
}
private void verifyRateLimit(LoadBalancer lb) throws InsufficientRequestException, StingrayRestClientException {
String vsName = loadBalancerName();
try {
Bandwidth bandwidth = client.getBandwidth(vsName);
BandwidthBasic basic = bandwidth.getProperties().getBasic();
Assert.assertEquals(basic.getMaximum(), lb.getRateLimit().getMaxRequestsPerSecond());
} catch(StingrayRestClientObjectNotFoundException notFoundException) {
Assert.assertNull(lb.getRateLimit());
}
}
private String readFile(File file) throws FileNotFoundException {
Scanner reader = new Scanner(file);
String content = "";
while (reader.hasNextLine()) content += reader.nextLine();
reader.close();
return content;
}
}