/* * 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 org.apache.ambari.funtest.server.tests; import java.io.File; import java.io.IOException; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.SQLNonTransientConnectionException; import java.util.Properties; import org.apache.ambari.funtest.server.LocalAmbariServer; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.ControllerModule; import org.apache.ambari.server.orm.DBAccessor; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.persist.PersistService; /** * Base test infrastructure. */ public class ServerTestBase { private static Log LOG = LogFactory.getLog(ServerTestBase.class); /** * Run the ambari server on a thread. */ protected static Thread serverThread = null; /** * Instance of the local ambari server, which wraps the actual * ambari server with test configuration. */ protected static LocalAmbariServer server = null; /** * Server port */ protected static int serverPort = 9995; /** * Server agent port */ protected static int serverAgentPort = 9000; /** * Guice injector using an in-memory DB. */ protected static Injector injector = null; /** * Server URL */ protected static String SERVER_URL_FORMAT = "http://localhost:%d"; /** * Initialize the AmbariServer and database once for the entire * duration of the tests since AmbariServer is a singleton. */ private static boolean isInitialized; /** * Create and populate the DB. Start the AmbariServer. * @throws Exception */ @BeforeClass public static void setupTest() throws Exception { if (!isInitialized) { Properties properties = new Properties(); properties.setProperty(Configuration.SERVER_PERSISTENCE_TYPE.getKey(), "remote"); properties.setProperty(Configuration.SERVER_JDBC_URL.getKey(), Configuration.JDBC_IN_MEMORY_URL); properties.setProperty(Configuration.SERVER_JDBC_DRIVER.getKey(), Configuration.JDBC_IN_MEMORY_DRIVER); properties.setProperty(Configuration.METADATA_DIR_PATH.getKey(), "src/test/resources/stacks"); properties.setProperty(Configuration.SERVER_VERSION_FILE.getKey(), "src/test/resources/version"); properties.setProperty(Configuration.OS_VERSION.getKey(), "centos6"); properties.setProperty(Configuration.SHARED_RESOURCES_DIR.getKey(), "src/test/resources/"); properties.setProperty(Configuration.AGENT_USE_SSL.getKey(), "false"); properties.setProperty(Configuration.CLIENT_API_PORT.getKey(), Integer.toString(serverPort)); properties.setProperty(Configuration.SRVR_ONE_WAY_SSL_PORT.getKey(), Integer.toString(serverAgentPort)); String tmpDir = System.getProperty("java.io.tmpdir"); properties.setProperty(Configuration.SRVR_KSTR_DIR.getKey(), tmpDir); ControllerModule testModule = new ControllerModule(properties); injector = Guice.createInjector(testModule); injector.getInstance(PersistService.class).start(); initDB(); server = injector.getInstance(LocalAmbariServer.class); serverThread = new Thread(server); serverThread.start(); waitForServer(); isInitialized = true; } } /** * Creates the basic authentication string for admin:admin * * @return */ protected static String getBasicAdminAuthentication() { String authString = getAdminUserName() + ":" + getAdminPassword(); byte[] authEncBytes = Base64.encodeBase64(authString.getBytes()); String authStringEnc = new String(authEncBytes); return "Basic " + authStringEnc; } /** * Creates the DB and populates it. * * @throws IOException * @throws SQLException */ protected static void initDB() throws IOException, SQLException { createSourceDatabase(); } /** * Drops the Derby DB. * * @throws ClassNotFoundException * @throws SQLException */ protected static void dropDatabase() throws ClassNotFoundException, SQLException { String DROP_DERBY_URL = "jdbc:derby:memory:myDB/ambari;drop=true"; Class.forName(Configuration.JDBC_IN_MEMORY_DRIVER); try { DriverManager.getConnection(DROP_DERBY_URL); } catch (SQLNonTransientConnectionException ignored) { LOG.info("Database dropped ", ignored); //error 08006 expected } } /** * Executes Ambari-DDL-Derby-CREATE.sql * * @throws IOException * @throws SQLException */ private static void createSourceDatabase() throws IOException, SQLException { //create database File projectDir = new File(System.getProperty("user.dir")); File ddlFile = new File(projectDir.getParentFile(), "ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql"); String ddlFilename = ddlFile.getPath(); DBAccessor dbAccessor = injector.getInstance(DBAccessor.class); dbAccessor.executeScript(ddlFilename); } /** * Gets the default administration user name * * @return */ protected static String getAdminUserName() { return "admin"; } /** * Gets the default administrator password * * @return */ protected static String getAdminPassword() { return "admin"; } /** * Waits for the local server until it is ready to accept requests. * * @throws Exception */ private static void waitForServer() throws Exception { int count = 1; while (!isServerUp()) { serverThread.join(count * 10000); // Give a few seconds for the ambari server to start up //count += 1; // progressive back off //count *= 2; // exponential back off } } /** * Attempt to query the server for the stack. If the server is up, * we will get a response. If not, an exception will be thrown. * * @return - True if the local server is responsive to queries. * False, otherwise. */ private static boolean isServerUp() throws IOException { String apiPath = "/api/v1/stacks"; String apiUrl = String.format(SERVER_URL_FORMAT, serverPort) + apiPath; CloseableHttpClient httpClient = HttpClients.createDefault();; try { HttpGet httpGet = new HttpGet(apiUrl); httpGet.addHeader("Authorization", getBasicAdminAuthentication()); httpGet.addHeader("X-Requested-By", "ambari"); HttpResponse httpResponse = httpClient.execute(httpGet); int statusCode = httpResponse.getStatusLine().getStatusCode(); HttpEntity entity = httpResponse.getEntity(); String responseBody = entity != null ? EntityUtils.toString(entity) : null; return true; } catch (IOException ex) { } finally { httpClient.close(); } return false; } /** * Perform common initialization for each test case. * * @throws Exception */ @Before public void setup() throws Exception { } /** * Perform common clean up for each test case. * * @throws Exception */ @After public void teardown() throws Exception { } }