diff --git a/pom.xml b/pom.xml index 218e5515033..6f7bd349edd 100644 --- a/pom.xml +++ b/pom.xml @@ -61,8 +61,8 @@ 1.7.2 14.0-rc1 6.2.0-3.1 - 3.1 - 4.2.1 + 4.3.6 + 4.4 5.1.21 1.3.1 3.1.3 @@ -323,7 +323,7 @@ org.apache.httpcomponents httpclient - ${cs.httpcore.version} + ${cs.httpclient.version} com.thoughtworks.xstream diff --git a/server/pom.xml b/server/pom.xml index c16185093f8..504bedcda0a 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -50,6 +50,7 @@ org.apache.httpcomponents httpcore + ${cs.httpcore.version} org.apache.cloudstack diff --git a/services/secondary-storage/server/pom.xml b/services/secondary-storage/server/pom.xml index 9643f9f6d8e..45fb1c37c99 100644 --- a/services/secondary-storage/server/pom.xml +++ b/services/secondary-storage/server/pom.xml @@ -53,6 +53,17 @@ cloud-server ${project.version} + + + org.apache.httpcomponents + httpcore + ${cs.httpcore.version} + + + org.apache.httpcomponents + httpcore-nio + ${cs.httpcore.version} + diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 457f1a23639..1bb48d4207b 100755 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -32,8 +32,10 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.io.InterruptedIOException; import java.math.BigInteger; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.URI; import java.net.UnknownHostException; import java.security.MessageDigest; @@ -48,19 +50,48 @@ import javax.naming.ConfigurationException; import com.cloud.utils.nio.HandlerFactory; import com.cloud.utils.nio.Link; -import com.cloud.utils.nio.NioServer; import com.cloud.utils.nio.Task; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.StringUtils; +import org.apache.http.Header; import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.config.ConnectionConfig; +import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.impl.nio.DefaultHttpServerIODispatch; +import org.apache.http.impl.nio.DefaultNHttpServerConnection; +import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory; +import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor; +import org.apache.http.impl.nio.reactor.IOReactorConfig; +import org.apache.http.nio.NHttpConnectionFactory; +import org.apache.http.nio.NHttpServerConnection; +import org.apache.http.nio.protocol.BasicAsyncRequestConsumer; +import org.apache.http.nio.protocol.BasicAsyncResponseProducer; +import org.apache.http.nio.protocol.HttpAsyncExchange; +import org.apache.http.nio.protocol.HttpAsyncRequestConsumer; +import org.apache.http.nio.protocol.HttpAsyncRequestHandler; +import org.apache.http.nio.protocol.HttpAsyncService; +import org.apache.http.nio.protocol.UriHttpAsyncRequestHandlerMapper; +import org.apache.http.nio.reactor.IOEventDispatch; +import org.apache.http.nio.reactor.ListeningIOReactor; +import org.apache.http.protocol.HttpContext; +import org.apache.http.protocol.HttpProcessor; +import org.apache.http.protocol.HttpProcessorBuilder; +import org.apache.http.protocol.ResponseConnControl; +import org.apache.http.protocol.ResponseContent; +import org.apache.http.protocol.ResponseDate; +import org.apache.http.protocol.ResponseServer; +import org.apache.http.util.EntityUtils; import org.apache.log4j.Logger; import com.amazonaws.services.s3.model.S3ObjectSummary; @@ -1309,9 +1340,61 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S private void startNioServerForPostUpload() { //TODO: make port configurable. - NioServer server = new NioServer("PostUploadServer", 8210, 15, this); - s_logger.info("Listening on 8210 with 15 workers"); - server.start(); + int port = 8210; + // Create HTTP protocol processing chain + HttpProcessor httpproc = HttpProcessorBuilder.create() + .add(new ResponseDate()) + .add(new ResponseServer("HTTP/1.1")) + .add(new ResponseContent()) + .add(new ResponseConnControl()).build(); + // Create request handler registry + UriHttpAsyncRequestHandlerMapper reqistry = new UriHttpAsyncRequestHandlerMapper(); + // Register the default handler for all URIs + reqistry.register("/upload*", new PostUploadRequestHandler()); + // Create server-side HTTP protocol handler + HttpAsyncService protocolHandler = new HttpAsyncService(httpproc, reqistry) { + + @Override + public void connected(final NHttpServerConnection conn) { + s_logger.info(conn + ": connection open"); + super.connected(conn); + } + + @Override + public void closed(final NHttpServerConnection conn) { + s_logger.info(conn + ": connection closed"); + super.closed(conn); + } + + }; + // Create HTTP connection factory + NHttpConnectionFactory connFactory; + + connFactory = new DefaultNHttpServerConnectionFactory( + ConnectionConfig.DEFAULT); + // Create server-side I/O event dispatch + IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(protocolHandler, connFactory); + // Set I/O reactor defaults + IOReactorConfig config = IOReactorConfig.custom() + .setIoThreadCount(15) + .setSoTimeout(3000) + .setConnectTimeout(3000) + .build(); + + try { + // Create server-side I/O reactor + ListeningIOReactor ioReactor = new DefaultListeningIOReactor(config); + + // Listen of the given port + ioReactor.listen(new InetSocketAddress(port)); + // Ready to go! + ioReactor.execute(ioEventDispatch); + } catch (InterruptedIOException ex) { + s_logger.info("Interrupted"); + } catch (IOException e) { + s_logger.info("I/O error: " + e.getMessage()); + } + s_logger.info("Shutdown"); } private void savePostUploadPSK(String psk) { @@ -2529,4 +2612,54 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S // TODO Auto-generated method stub } } + + //TODO: move this class to a separate file + private class PostUploadRequestHandler implements HttpAsyncRequestHandler { + public void handleInternal(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException { + + s_logger.info(""); // empty line before each request + s_logger.info(httpRequest.getRequestLine()); + s_logger.info("-------- HEADERS --------"); + for (Header header : httpRequest.getAllHeaders()) { + s_logger.info(header.getName() + " : " + header.getValue()); + } + s_logger.info("--------"); + + HttpEntity entity = null; + if (httpRequest instanceof HttpEntityEnclosingRequest) { + entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity(); + } + + if (entity != null) { + s_logger.info(entity.getContentType()); + s_logger.info(entity.getContentLength()); + s_logger.info(entity.isChunked()); + } + // For some reason, just putting the incoming entity into + // the response will not work. We have to buffer the message. + byte[] data; + if (entity == null) { + data = new byte[0]; + } else { + data = EntityUtils.toByteArray(entity); + } + + s_logger.info(new String(data)); + //TODO: post request is available in data. Need to parse and save file. + + httpResponse.setEntity(new StringEntity("upload successful")); + } + + @Override + public HttpAsyncRequestConsumer processRequest(HttpRequest request, HttpContext context) throws HttpException, IOException { + return new BasicAsyncRequestConsumer(); + } + + @Override + public void handle(HttpRequest request, HttpAsyncExchange httpExchange, HttpContext context) throws HttpException, IOException { + HttpResponse response = httpExchange.getResponse(); + handleInternal(request, response, context); + httpExchange.submitResponse(new BasicAsyncResponseProducer(response)); + } + } } diff --git a/systemvm/patches/debian/config/etc/apache2/sites-available/default-ssl b/systemvm/patches/debian/config/etc/apache2/sites-available/default-ssl index 710d038e572..4cd2b169d65 100644 --- a/systemvm/patches/debian/config/etc/apache2/sites-available/default-ssl +++ b/systemvm/patches/debian/config/etc/apache2/sites-available/default-ssl @@ -171,7 +171,7 @@ RewriteEngine Off RewriteCond %{HTTPS} =on RewriteCond %{REQUEST_METHOD} =POST - RewriteRule ^/upload/(.*) https://127.0.0.1:8210/upload?uuid=$1 [P,L] + RewriteRule ^/upload/(.*) http://127.0.0.1:8210/upload?uuid=$1 [P,L] diff --git a/test/pom.xml b/test/pom.xml index 158e35b0c18..e64f05124be 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -64,11 +64,6 @@ selenium-java-client-driver 1.0.1 - - commons-httpclient - commons-httpclient - ${cs.httpclient.version} - compile