/** * Copyright 2013-2015 Seagate Technology LLC. * * This Source Code Form is subject to the terms of the Mozilla * Public License, v. 2.0. If a copy of the MPL was not * distributed with this file, You can obtain one at * https://mozilla.org/MP:/2.0/. * * This program is distributed in the hope that it will be useful, * but is provided AS-IS, WITHOUT ANY WARRANTY; including without * the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or * FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public * License for more details. * * See www.openkinetic.org for more project information */ package com.seagate.kinetic; import org.testng.Assert; import java.io.File; import java.io.IOException; import java.util.logging.Logger; import kinetic.client.ClientConfiguration; import kinetic.client.KineticClient; import kinetic.client.KineticClientFactory; import kinetic.client.KineticException; import kinetic.simulator.KineticSimulator; import kinetic.simulator.SimulatorConfiguration; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import com.leacox.process.FinalizedProcess; import com.leacox.process.FinalizedProcessBuilder; import com.seagate.kinetic.client.internal.MessageFactory; import com.seagate.kinetic.common.lib.KineticMessage; import com.seagate.kinetic.proto.Kinetic.Command; import com.seagate.kinetic.simulator.lib.MyLogger; /** * Wrapper around java simulator for use in tests. Handles checking System * properties to see if the user wanted to run the tests against the Java * simulator or some other external device and starts a server as appropriate */ public class KineticTestSimulator { private final static Logger LOG = MyLogger.get(); private final String host; private final int port; private final KineticSimulator kineticServer; private final SimulatorConfiguration javaServerConfiguration; private final FinalizedProcess externalKineticServer; /** * * Create test simulator. * * @param clearExistingDatabase * If clear existing data, set true, if not, set false. * */ public KineticTestSimulator(boolean clearExistingDatabase) throws IOException, InterruptedException, KineticException { this(clearExistingDatabase, new SimulatorConfiguration()); } /** * * Create test simulator. * * @param clearExistingDatabase * If clear existing data, set true, if not, set false. * @param serverConfiguration * Using different configuration to generate different simulator. * * @throws KineticException * if any internal error occurred. * @throws IOException * if any IO error occurred * @throws InterruptedException * if any Interrupt error occurred * * @see SimulatorConfiguration */ public KineticTestSimulator(boolean clearExistingDatabase, SimulatorConfiguration serverConfiguration) throws IOException, InterruptedException, KineticException { javaServerConfiguration = serverConfiguration; String kineticPath = System.getProperty("KINETIC_PATH"); String kineticHost = System.getProperty("KINETIC_HOST"); int requestedPort = Integer.parseInt(System.getProperty("KINETIC_PORT", "8123")); if (!Boolean.parseBoolean(System.getProperty("RUN_AGAINST_EXTERNAL"))) { port = 8123; LOG.fine("Starting java simulator on port " + port); host = "localhost"; serverConfiguration.setPort(port); if (clearExistingDatabase) { deleteJavaServerAuxilaryData(); String defaultHome = System.getProperty("user.home") + File.separator + "leafcutter"; String leafcutterHome = serverConfiguration.getProperty( SimulatorConfiguration.KINETIC_HOME, defaultHome); FileUtils.deleteQuietly(new File(leafcutterHome)); } // set nio services thread pool size serverConfiguration.setNioServiceBossThreads(1); serverConfiguration.setNioServiceWorkerThreads(1); kineticServer = new KineticSimulator(serverConfiguration); externalKineticServer = null; } else if (kineticPath != null) { port = requestedPort; LOG.fine("Running tests against external simulator at " + kineticPath + " using port " + port); host = "localhost"; kineticServer = null; FinalizedProcessBuilder finalizedProcessBuilder = new FinalizedProcessBuilder( "killall", "-9", "kineticd"); finalizedProcessBuilder.start().waitFor(10 * 1000); Thread.sleep(500); // Since the cluster version is checked before performing an ISE we // need to manually remove // the file used to store the cluster version if (clearExistingDatabase) { final String workingDirectory = FilenameUtils .getFullPath(kineticPath); final String clusterStorePath = FilenameUtils.concat( workingDirectory, "cluster_version"); FileUtils.deleteQuietly(new File(clusterStorePath)); } finalizedProcessBuilder = new FinalizedProcessBuilder(kineticPath); finalizedProcessBuilder.directory(new File(".")); finalizedProcessBuilder.gobbleStreamsWithLogging(true); externalKineticServer = finalizedProcessBuilder.start(); waitForServerReady(); } else { host = kineticHost; port = requestedPort; LOG.fine("Running tests against " + host + ":" + port); kineticServer = null; externalKineticServer = null; } if (clearExistingDatabase) { KineticClient kineticClient = buildClient(); KineticMessage km = MessageFactory.createKineticMessageWithBuilder(); Command.Builder commandBuillder = (Command.Builder) km.getCommand(); commandBuillder.getBodyBuilder().getSetupBuilder(); /** * XXX protocol-3.0.0 */ //com.seagate.kinetic.proto.Kinetic.Message.Builder builder = com.seagate.kinetic.proto.Kinetic.Message // .newBuilder(); //builder.getCommandBuilder().getBodyBuilder().getSetupBuilder() //.setInstantSecureErase(true); commandBuillder .getHeaderBuilder() .setMessageType( com.seagate.kinetic.proto.Kinetic.Command.MessageType.SETUP); kineticClient.request(km); kineticClient.close(); } } /** * * Sleep enough time for simulator start and close. * * @throws InterruptedException * If any interrupt error occurred. * */ private void waitForServerReady() throws InterruptedException { final int pollingIntervalMS = 50; final int maxWaitTimeSec = 10; long waitStartTime = System.currentTimeMillis(); float elapsedTimeMS; while (true) { Thread.sleep(pollingIntervalMS); elapsedTimeMS = System.currentTimeMillis() - waitStartTime; if (elapsedTimeMS > maxWaitTimeSec * 1000) { throw new RuntimeException("Server never became available"); } try { KineticClient kineticClient = buildClient(); kineticClient.noop(); kineticClient.close(); break; } catch (KineticException e) { // Since all exceptions get turned into KineticException we have // to manually check the message if (e.getMessage().contains("Kinetic Command Exception: ")) { break; } // Ignore this exception because it probably means that the // server isn't ready yet so // we'll just take a brief nap and try again in a bit } } LOG.info("Server ready after waiting ms: " + elapsedTimeMS); } /** * * Get simulator port info. * * @return port return port info. * */ public int getPort() { return port; } /** * * close simulator. * * @throws IOException * if any IO error occurred. * */ public void shutdown() throws IOException { if (kineticServer != null) { LOG.fine("Stopping Java simulator"); kineticServer.close(); } if (externalKineticServer != null) { externalKineticServer.close(); } } /** * * Generate a Kinetic client. * * @throws KineticException * if any internal error occurred. * */ public KineticClient buildClient() throws KineticException { return KineticClientFactory.createInstance(buildClientConfig()); } /** * * Generate a Kinetic client configuration. * */ public ClientConfiguration buildClientConfig() { ClientConfiguration clientConfig = new ClientConfiguration(); clientConfig.setHost(host); clientConfig.setPort(getPort()); // nio service threads in pool clientConfig.setNioServiceThreads(1); return clientConfig; } /** * * Clean data after every test. * */ public void deleteJavaServerAuxilaryData() { String kineticHome = System.getProperty("user.home") + File.separator + "kinetic"; if (javaServerConfiguration .getProperty(SimulatorConfiguration.KINETIC_HOME) != null) { kineticHome = javaServerConfiguration .getProperty(SimulatorConfiguration.KINETIC_HOME); } // Delete ACLs FileUtils .deleteQuietly(new File(kineticHome + File.separator + ".acl")); FileUtils.deleteQuietly(new File(kineticHome + File.separator + ".acl.bak")); // Delete setup files FileUtils.deleteQuietly(new File(kineticHome + File.separator + ".setup")); FileUtils.deleteQuietly(new File(kineticHome + File.separator + ".setup.bak")); // Delete history files try { FileUtils.deleteDirectory(new File(kineticHome + File.separator + javaServerConfiguration .getProperty(SimulatorConfiguration.PERSIST_HOME))); FileUtils.deleteQuietly(new File(kineticHome + File.separator + ".acl")); } catch (IOException e) { Assert.fail("delete directory failed" + e.getMessage()); } } }