// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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 com.cloud.test.utils;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;
import org.apache.log4j.NDC;
import com.trilead.ssh2.ChannelCondition;
import com.trilead.ssh2.Connection;
import com.trilead.ssh2.SCPClient;
import com.trilead.ssh2.Session;
public class TestClient {
private static long sleepTime = 180000L; // default 0
private static boolean cleanUp = true;
public static final Logger s_logger = Logger.getLogger(TestClient.class.getName());
private static boolean repeat = true;
private static int numOfUsers = 0;
private static String[] users = null;
private static boolean internet = true;
private static final int MAX_RETRY_LINUX = 5;
private static final int MAX_RETRY_WIN = 10;
public static void main(String[] args) {
String host = "http://localhost";
String port = "8080";
String testUrl = "/client/test";
int numThreads = 1;
try {
// Parameters
List<String> argsList = Arrays.asList(args);
Iterator<String> iter = argsList.iterator();
while (iter.hasNext()) {
String arg = iter.next();
// host
if (arg.equals("-h")) {
host = "http://" + iter.next();
}
if (arg.equals("-p")) {
port = iter.next();
}
if (arg.equals("-t")) {
numThreads = Integer.parseInt(iter.next());
}
if (arg.equals("-s")) {
sleepTime = Long.parseLong(iter.next());
}
if (arg.equals("-c")) {
cleanUp = Boolean.parseBoolean(iter.next());
if (!cleanUp)
sleepTime = 0L; // no need to wait if we don't ever cleanup
}
if (arg.equals("-r")) {
repeat = Boolean.parseBoolean(iter.next());
}
if (arg.equals("-u")) {
numOfUsers = Integer.parseInt(iter.next());
}
if (arg.equals("-i")) {
internet = Boolean.parseBoolean(iter.next());
}
}
final String server = host + ":" + port + testUrl;
s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)");
if (cleanUp)
s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up");
if (numOfUsers > 0) {
s_logger.info("Pre-generating users for test of size : " + numOfUsers);
users = new String[numOfUsers];
Random ran = new Random();
for (int i = 0; i < numOfUsers; i++) {
users[i] = Math.abs(ran.nextInt()) + "-user";
}
}
for (int i = 0; i < numThreads; i++) {
new Thread(new Runnable() {
@Override
public void run() {
do {
String username = null;
try {
long now = System.currentTimeMillis();
Random ran = new Random();
if (users != null) {
username = users[Math.abs(ran.nextInt()) % numOfUsers];
} else {
username = Math.abs(ran.nextInt()) + "-user";
}
NDC.push(username);
String url = server + "?email=" + username + "&password=" + username + "&command=deploy";
s_logger.info("Launching test for user: " + username + " with url: " + url);
HttpClient client = new HttpClient();
HttpMethod method = new GetMethod(url);
int responseCode = client.executeMethod(method);
boolean success = false;
String reason = null;
if (responseCode == 200) {
if (internet) {
s_logger.info("Deploy successful...waiting 5 minute before SSH tests");
Thread.sleep(300000L); // Wait 60 seconds so the linux VM can boot up.
s_logger.info("Begin Linux SSH test");
reason = sshTest(method.getResponseHeader("linuxIP").getValue());
if (reason == null) {
s_logger.info("Linux SSH test successful");
s_logger.info("Begin Windows SSH test");
reason = sshWinTest(method.getResponseHeader("windowsIP").getValue());
}
}
if (reason == null) {
if (internet) {
s_logger.info("Windows SSH test successful");
} else {
s_logger.info("deploy test successful....now cleaning up");
if (cleanUp) {
s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms");
Thread.sleep(sleepTime);
} else {
success = true;
}
}
if (users == null) {
s_logger.info("Sending cleanup command");
url = server + "?email=" + username + "&password=" + username + "&command=cleanup";
} else {
s_logger.info("Sending stop DomR / destroy VM command");
url = server + "?email=" + username + "&password=" + username + "&command=stopDomR";
}
method = new GetMethod(url);
responseCode = client.executeMethod(method);
if (responseCode == 200) {
success = true;
} else {
reason = method.getStatusText();
}
} else {
// Just stop but don't destroy the VMs/Routers
s_logger.info("SSH test failed with reason '" + reason + "', stopping VMs");
url = server + "?email=" + username + "&password=" + username + "&command=stop";
responseCode = client.executeMethod(new GetMethod(url));
}
} else {
// Just stop but don't destroy the VMs/Routers
reason = method.getStatusText();
s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs");
url = server + "?email=" + username + "&password=" + username + "&command=stop";
client.executeMethod(new GetMethod(url));
}
if (success) {
s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds");
} else {
s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) +
" seconds with reason : " + reason);
}
} catch (Exception e) {
s_logger.warn("Error in thread", e);
try {
HttpClient client = new HttpClient();
String url = server + "?email=" + username + "&password=" + username + "&command=stop";
client.executeMethod(new GetMethod(url));
} catch (Exception e1) {
s_logger.info("[ignored]"
+ "error while executing last resort stop attampt: " + e1.getLocalizedMessage());
}
} finally {
NDC.clear();
}
} while (repeat);
}
}).start();
}
} catch (Exception e) {
s_logger.error(e);
}
}
private static String sshWinTest(String host) {
if (host == null) {
s_logger.info("Did not receive a host back from test, ignoring win ssh test");
return null;
}
// We will retry 5 times before quitting
int retry = 0;
while (true) {
try {
if (retry > 0) {
s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt");
Thread.sleep(300000);
}
s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry);
Connection conn = new Connection(host);
conn.connect(null, 60000, 60000);
s_logger.info("SSHed successfully into windows host " + host);
boolean success = false;
boolean isAuthenticated = conn.authenticateWithPassword("vmops", "vmops");
if (isAuthenticated == false) {
return "Authentication failed";
}
SCPClient scp = new SCPClient(conn);
scp.put("wget.exe", "");
Session sess = conn.openSession();
s_logger.info("Executing : wget http://172.16.0.220/dump.bin");
sess.execCommand("wget http://172.16.0.220/dump.bin && dir dump.bin");
InputStream stdout = sess.getStdout();
InputStream stderr = sess.getStderr();
byte[] buffer = new byte[8192];
while (true) {
if ((stdout.available() == 0) && (stderr.available() == 0)) {
int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000);
if ((conditions & ChannelCondition.TIMEOUT) != 0) {
s_logger.info("Timeout while waiting for data from peer.");
return null;
}
if ((conditions & ChannelCondition.EOF) != 0) {
if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) {
break;
}
}
}
while (stdout.available() > 0) {
success = true;
int len = stdout.read(buffer);
if (len > 0) // this check is somewhat paranoid
s_logger.info(new String(buffer, 0, len));
}
while (stderr.available() > 0) {
int len = stderr.read(buffer);
}
}
sess.close();
conn.close();
if (success) {
return null;
} else {
retry++;
if (retry == MAX_RETRY_WIN) {
return "SSH Windows Network test fail";
}
}
} catch (Exception e) {
retry++;
if (retry == MAX_RETRY_WIN) {
return "SSH Windows Network test fail with error " + e.getMessage();
}
}
}
}
private static String sshTest(String host) {
if (host == null) {
s_logger.info("Did not receive a host back from test, ignoring ssh test");
return null;
}
// We will retry 5 times before quitting
int retry = 0;
while (true) {
try {
if (retry > 0) {
s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt");
Thread.sleep(120000);
}
s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry);
Connection conn = new Connection(host);
conn.connect(null, 60000, 60000);
s_logger.info("SSHed successfully into linux host " + host);
boolean isAuthenticated = conn.authenticateWithPassword("root", "password");
if (isAuthenticated == false) {
return "Authentication failed";
}
boolean success = false;
Session sess = conn.openSession();
s_logger.info("Executing : wget http://172.16.0.220/dump.bin");
sess.execCommand("wget http://172.16.0.220/dump.bin && ls -al dump.bin");
InputStream stdout = sess.getStdout();
InputStream stderr = sess.getStderr();
byte[] buffer = new byte[8192];
while (true) {
if ((stdout.available() == 0) && (stderr.available() == 0)) {
int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000);
if ((conditions & ChannelCondition.TIMEOUT) != 0) {
s_logger.info("Timeout while waiting for data from peer.");
return null;
}
if ((conditions & ChannelCondition.EOF) != 0) {
if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) {
break;
}
}
}
while (stdout.available() > 0) {
success = true;
int len = stdout.read(buffer);
if (len > 0) // this check is somewhat paranoid
s_logger.info(new String(buffer, 0, len));
}
while (stderr.available() > 0) {
int len = stderr.read(buffer);
}
}
sess.close();
conn.close();
if (success) {
return null;
} else {
retry++;
if (retry == MAX_RETRY_LINUX) {
return "SSH Linux Network test fail";
}
}
} catch (Exception e) {
retry++;
if (retry == MAX_RETRY_LINUX) {
return "SSH Linux Network test fail with error " + e.getMessage();
}
}
}
}
}