/* * RHQ Management Platform * Copyright (C) 2005-2014 Red Hat, Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.enterprise.server.core; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.Properties; import java.util.Random; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; import java.util.jar.Manifest; import javax.persistence.Query; import org.testng.annotations.Test; import org.rhq.core.clientapi.server.core.AgentRegistrationException; import org.rhq.core.clientapi.server.core.AgentRegistrationRequest; import org.rhq.core.clientapi.server.core.AgentRegistrationResults; import org.rhq.core.clientapi.server.core.AgentVersion; import org.rhq.core.domain.cloud.Server; import org.rhq.core.domain.cloud.Server.OperationMode; import org.rhq.core.domain.common.ProductInfo; import org.rhq.core.domain.install.remote.AgentInstall; import org.rhq.core.domain.resource.Agent; import org.rhq.core.util.exception.ThrowableUtil; import org.rhq.core.util.stream.StreamUtil; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.test.AbstractEJB3Test; import org.rhq.enterprise.server.util.LookupUtil; import org.rhq.enterprise.server.util.ServerFactory; /** * This tests the core server service. This includes agent registration. * * @author John Mazzitelli */ // These are the agent registration unit test cases. // (allowed) means the registration should succeed. // (REJECT) means the server should reject that agent registration request. // --- // A. testNewAgentRegistrationWithOldToken // 1) register a new agent with a non-null, unknown security token (allowed) // B. testChangeAddressPort // 1) register a new agent Z with null security token (allowed) // 2) re-register agent Z with its token but change its host (allowed) // 3) re-register agent Z with its token but change its port (allowed) // 4) re-register agent Z with its token but change its host and port (allowed) // 5) re-register agent Z with its token but change nothing (allowed) // 6) re-register agent Z with NO token but change its host (REJECT) // 7) re-register agent Z with NO token but change its port (REJECT) // 8) re-register agent Z with NO token but change its host and port (REJECT) // 9) re-register agent Z with NO token but change nothing (REJECT) // C. testNormalAgentRegistration // 1) register a new agent A with a null security token (allowed, same as B.1) // D. testHijackExistingAgentAddressPort // 1) register a new agent B with null security token but using A's host/port (REJECT) // E. testHijackExistingAgentName // 1) register an agent using an already-existing agent name A, and using A's host but a different port with a null token (REJECT - missing the token) // 2) register an agent using an already-existing agent name A, and using A's port but a different host with a null token (REJECT - missing the token) // 3) register an agent using an already-existing agent name A, and using a different port and host with a null token (REJECT - missing the token) // F. testHijackExistingAgentAddressPortWithBogusToken // 1) register a new agent B with A's host and port but with a bogus token (REJECT) // G. testHijackExistingAgentNameWithBogusToken // 1) re-register agent A with its original host and port but with a bogus token (REJECT) // 2) re-register agent A with its original host, different port but with bogus token (REJECT) // 3) re-register agent A with different host, original port but with bogus token (REJECT) // 4) re-register agent A with different host and port but with bogus token (REJECT) // H. testHijackExistingAgentNameWithAnotherAgentToken // 1) re-register agent A with its original host and port but with Z's security token (REJECT - you cannot authenticate using another agent's token) // 2) re-register agent A with different host and original port but with Z's security token (REJECT - you cannot authenticate using another agent's token) // 3) re-register agent A with original host and different port but with Z's security token (REJECT - you cannot authenticate using another agent's token) // 4) re-register agent A with different host and port but with Z's security token (REJECT - you cannot authenticate using another agent's token) // I. testAgentHijackingAnotherAgentAddressPort // 1) re-register agent A using A's correct security token but with Z's host and Z's port (REJECT - one agent cannot steal another agent's host/port endpoint) NOTE: this is not D.1 because in D.1, the request doesn't have a token. This I.1 test has a token and it really authenticates the agent A making the request. This also isn't F.1 because F.1, while it has a token, it is not a valid token, thus its agent is not authentic. // J. testAttemptToChangeAgentName // 1) register agent "newName" but with Z's host/port/token. In effect, this is trying to change the agent's name. (REJECT - you are not allowed to rename agents) @SuppressWarnings("unchecked") @Test(groups = { "core.agent.registration" }) public class CoreServerServiceImplTest extends AbstractEJB3Test { private static final String TEST_AGENT_NAME_PREFIX = "CoreServerServiceImplTest.Agent"; private AgentVersion agentVersion; private Server server; private static final int A_PORT = 11111; private static final String A_HOST = "hostA"; private static final int B_PORT = 22222; private static final String B_HOST = "hostB"; private static final String VERSION = "1.2.3"; private static final String BUILD = "12345"; private static final String AGENT_VERSION = "rhq-agent.latest.version"; private static final String AGENT_BUILD = "rhq-agent.latest.build-number"; private static final String AGENT_MD5 = "rhq-agent.latest.md5"; //lives on the server/gui in agent/downloads folder private static final String SERVER_AGENT_PROPERTIES = "rhq-server-agent-versions.properties"; //lives in the agent jar root private static final String AGENT_UPDATE_PROPERTIES = "rhq-agent-update-version.properties"; private static final String DOWNLOADS_AGENT = "rhq-downloads/rhq-agent"; // README // Arquillian (1.0.2) does not honor Testng's lifecycle, Before/AfterClass are invoked on // every test. We use stand-in tests to simulate BeforeClass and AfterClass, using priorities // to make them run first and last. Testng (I believe) applies priority after dependencies, so it // is important that afterClassStandIn() have a dependency such that it runs in the last test-set. @Test(priority = -10) public void beforeClassStandIn() throws Exception { // delete our instance var object files, if they exist deleteObjects("a.obj"); deleteObjects("b.obj"); } @Test(priority = 10, dependsOnMethods = "testNormalAgentRegistration", alwaysRun = true) public void afterClassStandIn() throws Exception { // delete our instance var object files deleteObjects("a.obj"); deleteObjects("b.obj"); // clean up any agents we might have created Query q = getEntityManager().createQuery( "select a from Agent a where name like '" + TEST_AGENT_NAME_PREFIX + "%'"); List<Agent> doomed = q.getResultList(); for (Agent deleteMe : doomed) { LookupUtil.getAgentManager().deleteAgent(deleteMe); } } @Override protected void beforeMethod() throws Exception { // mock the name of our server via the sysprop (in production, this is normally set in rhq-server.properties) setServerIdentity("CoreServerServiceImplTest.Server"); // mock up our core server MBean that provides information about where the jboss home dir is DummyCoreServer mbean = new DummyCoreServer(); prepareCustomServerService(mbean, CoreServerMBean.OBJECT_NAME); // in order to register, we need to mock out the agent version file used by the server // to determine the agent version it supports. agentVersion = new AgentVersion(VERSION, BUILD); File agentVersionFile = new File(mbean.getJBossServerDataDir(), DOWNLOADS_AGENT + "/" + SERVER_AGENT_PROPERTIES); agentVersionFile.getParentFile().mkdirs(); agentVersionFile.delete(); Properties agentVersionProps = new Properties(); agentVersionProps.put(AGENT_VERSION, agentVersion.getVersion()); agentVersionProps.put(AGENT_BUILD, agentVersion.getBuild()); FileOutputStream fos = new FileOutputStream(agentVersionFile); try { agentVersionProps.store(fos, "This file was created by " + CoreServerServiceImplTest.class.getName()); } finally { fos.close(); } //#now build a fake agent.jar file as well for the tests. File testLocation = new File(getTempDir(), this.getClass().getSimpleName()); File serverVersionFile = new File(testLocation, DOWNLOADS_AGENT + "/" + SERVER_AGENT_PROPERTIES); File agentPropertiesFile = new File(testLocation, DOWNLOADS_AGENT + "/" + AGENT_UPDATE_PROPERTIES); FileInputStream fin = new FileInputStream(serverVersionFile); FileOutputStream fout = new FileOutputStream(agentPropertiesFile); //build out the version for the agent jar StreamUtil.copy(fin, fout, true); //generate fake agent file. File agentBinaryFile = new File(testLocation, DOWNLOADS_AGENT + "/agent.jar"); buildFakeAgentJar(agentVersionFile, agentBinaryFile); // make sure this is older than the version file agentBinaryFile.setLastModified(System.currentTimeMillis() - 600000); // this mocks out the endpoint ping - the server will think the agent that is registering is up and pingable prepareForTestAgents(); // mock our server server = ServerFactory.newInstance(); server.setName(getServerIdentity()); server.setAddress("CoreServerServiceImplTest.localhost"); server.setPort(12345); server.setSecurePort(12346); server.setOperationMode(OperationMode.NORMAL); int serverId = LookupUtil.getServerManager().create(server); server.setId(serverId); } @Override protected void afterMethod() throws Exception { // cleanup our test server LookupUtil.getTopologyManager().updateServerMode(LookupUtil.getSubjectManager().getOverlord(), new Integer[] { server.getId() }, OperationMode.DOWN); LookupUtil.getTopologyManager().deleteServer(LookupUtil.getSubjectManager().getOverlord(), server.getId()); // shutdown our mock mbean server unprepareCustomServerService(CoreServerMBean.OBJECT_NAME); unprepareForTestAgents(); } @Test public void testNewAgentRegistrationWithOldToken() throws Exception { // this tests the case where someone purged an agent from the DB, but then // changed their mind and want to re-run that agent and re-register it again. // In this case, the agent (if not using --cleanallconfig) would still have the old token. // The agent should still be allowed to register again. CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request = createRequest(prefixName("old"), "hostOld", 12345, "oldtoken"); AgentRegistrationResults results = service.registerAgent(request); assert results != null : "cannot re-register an old agent"; Agent agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken()); assert agent.getName().equals(request.getName()); assert agent.getAddress().equals(request.getAddress()); assert agent.getPort() == request.getPort(); LookupUtil.getAgentManager().deleteAgent(agent); } @Test public void testChangeAddressPort() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; AgentRegistrationResults results; String tuid = "" + new Random().nextInt(); //let's make this unique per run to support repeated individual runs. String zName = prefixName("Z" + "-" + tuid); // create a new agent Z with host/port of hostZ/55550 request = createRequest(zName, "hostZ", 55550, null); results = service.registerAgent(request); assert results != null : "got null results"; // now change Z's host to hostZprime request = createRequest(zName, "hostZprime", 55550, results.getAgentToken()); results = service.registerAgent(request); assert results != null; Agent agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken()); assert agent.getName().equals(zName); assert agent.getAddress().equals("hostZprime"); assert agent.getPort() == 55550; // now change Z's port to 55551 request = createRequest(zName, "hostZprime", 55551, results.getAgentToken()); results = service.registerAgent(request); assert results != null; agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken()); assert agent.getName().equals(zName); assert agent.getAddress().equals("hostZprime"); assert agent.getPort() == 55551; // now change Z's host/port to hostZdoubleprime/55552 request = createRequest(zName, "hostZdoubleprime" + tuid, 55552, results.getAgentToken()); results = service.registerAgent(request); assert results != null; agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken()); assert agent.getName().equals(zName); assert agent.getAddress().equals("hostZdoubleprime" + tuid); assert agent.getPort() == 55552; // now don't change Z's host/port but re-register everything the same with its token request = createRequest(zName, "hostZdoubleprime" + tuid, 55552, results.getAgentToken()); results = service.registerAgent(request); assert results != null; agent = LookupUtil.getAgentManager().getAgentByAgentToken(results.getAgentToken()); assert agent.getName().equals(zName); assert agent.getAddress().equals("hostZdoubleprime" + tuid); assert agent.getPort() == 55552; // remember this agent so our later tests can use it AgentRegistrationRequest zReq = request; AgentRegistrationResults zResults = results; writeObjects("b.obj", zReq, zResults); // Try to re-register changes to host and/or port but do not send any token. // Because there is no token, these should fail. request = createRequest(zName, B_HOST, zReq.getPort(), null); try { service.registerAgent(request); assert false : "(1) Should not have been able to register without a token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(zName, zReq.getAddress(), B_PORT, null); try { service.registerAgent(request); assert false : "(2) Should not have been able to register without a token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(zName, B_HOST, B_PORT, null); try { service.registerAgent(request); assert false : "(3) Should not have been able to register without a token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(zName, zReq.getAddress(), zReq.getPort(), null); try { service.registerAgent(request); assert false : "(4) Should not have been able to register without a token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } @Test(dependsOnMethods = "testChangeAddressPort") public void testNormalAgentRegistration() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest aReq = createRequest(prefixName("A"), A_HOST, A_PORT, null); AgentRegistrationResults aResults = service.registerAgent(aReq); assert aResults != null : "got null results"; writeObjects("a.obj", aReq, aResults); } @Test(dependsOnMethods = "testNormalAgentRegistration") public void testHijackExistingAgentAddressPort() throws Exception { List<Object> objs = readObjects("a.obj", 1); AgentRegistrationRequest aReq = (AgentRegistrationRequest) objs.get(0); CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; request = createRequest(prefixName("B"), aReq.getAddress(), aReq.getPort(), null); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used host/port with new agent name"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } @Test(dependsOnMethods = "testNormalAgentRegistration") public void testHijackExistingAgentName() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; List<Object> objs = readObjects("a.obj", 1); AgentRegistrationRequest aReq = (AgentRegistrationRequest) objs.get(0); request = createRequest(aReq.getName(), aReq.getAddress(), B_PORT, null); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used agent name without a token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), B_HOST, aReq.getPort(), null); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used agent name without a token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), B_HOST, B_PORT, null); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used agent name without a token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } @Test(dependsOnMethods = "testNormalAgentRegistration") public void testHijackExistingAgentAddressPortWithBogusToken() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; List<Object> objs = readObjects("a.obj", 1); AgentRegistrationRequest aReq = (AgentRegistrationRequest) objs.get(0); request = createRequest(prefixName("B"), aReq.getAddress(), aReq.getPort(), "badtoken"); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used host/port with new agent name and invalid token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } @Test(dependsOnMethods = "testNormalAgentRegistration") public void testHijackExistingAgentNameWithBogusToken() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; List<Object> objs = readObjects("a.obj", 1); AgentRegistrationRequest aReq = (AgentRegistrationRequest) objs.get(0); request = createRequest(aReq.getName(), aReq.getAddress(), aReq.getPort(), "badtoken"); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used agent name with an invalid token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), aReq.getAddress(), B_PORT, "badtoken"); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used agent name with an invalid token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), B_HOST, aReq.getPort(), "badtoken"); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used agent name with an invalid token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), B_HOST, B_PORT, "badtoken"); try { service.registerAgent(request); assert false : "Should not have been able to hijack a used agent name with an invalid token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } @Test(dependsOnMethods = "testNormalAgentRegistration") public void testHijackExistingAgentNameWithAnotherAgentToken() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; List<Object> objs = readObjects("a.obj", 1); AgentRegistrationRequest aReq = (AgentRegistrationRequest) objs.get(0); objs = readObjects("b.obj", 2); @SuppressWarnings("unused") AgentRegistrationRequest zReq = (AgentRegistrationRequest) objs.get(0); AgentRegistrationResults zResults = (AgentRegistrationResults) objs.get(1); request = createRequest(aReq.getName(), aReq.getAddress(), aReq.getPort(), zResults.getAgentToken()); try { service.registerAgent(request); assert false : "Should not have been able to hijack agent A using Z's token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), B_HOST, aReq.getPort(), zResults.getAgentToken()); try { service.registerAgent(request); assert false : "Should not have been able to hijack agent A using Z's token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), aReq.getAddress(), B_PORT, zResults.getAgentToken()); try { service.registerAgent(request); assert false : "Should not have been able to hijack agent A using Z's token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } request = createRequest(aReq.getName(), B_HOST, B_PORT, zResults.getAgentToken()); try { service.registerAgent(request); assert false : "Should not have been able to hijack agent A using Z's token"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } @Test(dependsOnMethods = "testNormalAgentRegistration") public void testAgentHijackingAnotherAgentAddressPort() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; List<Object> objs = readObjects("a.obj", 2); AgentRegistrationRequest aReq = (AgentRegistrationRequest) objs.get(0); AgentRegistrationResults aResults = (AgentRegistrationResults) objs.get(1); objs = readObjects("b.obj", 1); AgentRegistrationRequest zReq = (AgentRegistrationRequest) objs.get(0); request = createRequest(aReq.getName(), zReq.getAddress(), zReq.getPort(), aResults.getAgentToken()); try { service.registerAgent(request); assert false : "An agent should not have been able to hijack another agent's host/port"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } @Test(dependsOnMethods = "testNormalAgentRegistration") public void testAttemptToChangeAgentName() throws Exception { CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest request; List<Object> objs = readObjects("b.obj", 2); AgentRegistrationRequest zReq = (AgentRegistrationRequest) objs.get(0); AgentRegistrationResults zResults = (AgentRegistrationResults) objs.get(1); request = createRequest(prefixName("newName"), zReq.getAddress(), zReq.getPort(), zResults.getAgentToken()); try { service.registerAgent(request); assert false : "An agent should not be able to change its name"; } catch (AgentRegistrationException ok) { debugPrintThrowable(ok); } } /** Exercises the agentUpdateVersionFile mechanism. * verify that one is created if none exists before. */ @Test public void testAgentUpateVersionFile() { AgentManagerLocal agentManager = LookupUtil.getAgentManager(); String AGENT_VERSION = CoreServerServiceImplTest.AGENT_VERSION; String AGENT_BUILD = CoreServerServiceImplTest.AGENT_BUILD; String RHQ_AGENT_LATEST_MD5 = CoreServerServiceImplTest.AGENT_MD5; String version = VERSION; String build = BUILD; try { File updateFile = agentManager.getAgentUpdateVersionFile(); assert updateFile != null : "GetAgentUpdateVersionFile returned null."; Properties props = new Properties(); FileInputStream inStream = new FileInputStream(updateFile); try { props.load(inStream); } finally { inStream.close(); } //check that properties present boolean locatedAgentVersion = false; boolean locatedAgentBuild = false; for (Object property : props.keySet()) { if (property.toString().equals(AGENT_VERSION)) { locatedAgentVersion = true; } else if (property.toString().equals(AGENT_BUILD)) { locatedAgentBuild = true; } } assert locatedAgentVersion : AGENT_VERSION + " was not found."; assert locatedAgentBuild : AGENT_BUILD + " was not found."; //Now delete the file and test that it's recreated properly File testLocation = new File(getTempDir(), "CoreServerServiceImplTest"); File serverVersionFile = new File(testLocation, DOWNLOADS_AGENT + "/" + SERVER_AGENT_PROPERTIES); File agentVersionFile = new File(testLocation, DOWNLOADS_AGENT + "/" + AGENT_UPDATE_PROPERTIES); FileInputStream fin = new FileInputStream(serverVersionFile); FileOutputStream fout = new FileOutputStream(agentVersionFile); StreamUtil.copy(fin, fout, true); serverVersionFile.delete(); assert !serverVersionFile.exists() : "The default test file location still exists. Unable to proceed."; assert agentVersionFile.exists() : "The agent properties file was not created. Unable to proceed."; //update the mocked components necessary for regeneration DummyCoreServerTweaked mbean = new DummyCoreServerTweaked(version, build); prepareCustomServerService(mbean, CoreServerMBean.OBJECT_NAME); //generate fake agent file. File agentBinaryFile = new File(testLocation, DOWNLOADS_AGENT + "/agent.jar"); assert agentBinaryFile.exists() : "A fake agent binary file should already exist."; assert agentBinaryFile.delete() : "Unable to delete default binary file."; buildFakeAgentJar(agentVersionFile, agentBinaryFile); assert agentBinaryFile.exists() : "Failed to build fake agent file:" + agentBinaryFile.getCanonicalPath(); //trigger the file regeneration updateFile = agentManager.getAgentUpdateVersionFile(); //check values props = new Properties(); inStream = new FileInputStream(updateFile); try { props.load(inStream); } finally { inStream.close(); } locatedAgentVersion = false; locatedAgentBuild = false; for (Object property : props.keySet()) { if (property.toString().equals(AGENT_VERSION)) { locatedAgentVersion = true; } else if (property.toString().equals(AGENT_BUILD)) { locatedAgentBuild = true; } } //Verify regenerated bits. It's more than we deliver with a release assert locatedAgentVersion : AGENT_VERSION + " was not found."; assert props.getProperty(AGENT_VERSION).equals(version) : "Version field did not match. Expected '" + version + "' but got '" + props.getProperty(AGENT_VERSION) + "'."; assert locatedAgentBuild : AGENT_BUILD + " was not found."; assert props.getProperty(AGENT_BUILD).equals(build) : "Version field did not match. Expected '" + version + "' but got '" + props.getProperty(AGENT_BUILD) + "'."; assert props.getProperty(RHQ_AGENT_LATEST_MD5) != null : "MD5 value not located."; assert props.getProperty(RHQ_AGENT_LATEST_MD5).trim().length() > 0 : "No checksum value was located."; } catch (Exception e) { e.printStackTrace(); } } @Test public void testLinkAgentWithAgentInstall() throws Exception { AgentManagerLocal agentManager = LookupUtil.getAgentManager(); SubjectManagerLocal sm = LookupUtil.getSubjectManager(); AgentInstall persistedAgentInstall = agentManager.getAgentInstallByAgentName(sm.getOverlord(), "should-not-exist"); assert persistedAgentInstall == null; AgentInstall agentInstall = new AgentInstall(); agentInstall.setSshHost("CoreServerServiceImpl-SshHost"); agentInstall.setSshPort(44); agentInstall.setSshUsername("CoreServerServiceImpl-SshUsername"); agentInstall.setSshPassword("CoreServerServiceImpl-SshPassword"); agentInstall = agentManager.updateAgentInstall(sm.getOverlord(), agentInstall); assert agentInstall.getId() > 0 : "didn't persist properly - ID should be non-zero"; assert agentInstall.getAgentName() == null : "there should be no agent name yet"; assert agentInstall.getInstallLocation() == null : "there should be no install location yet"; CoreServerServiceImpl service = new CoreServerServiceImpl(); AgentRegistrationRequest aReq = createRequest(prefixName(".AgentInstall"), A_HOST, A_PORT, null, String.valueOf(agentInstall.getId()), "/tmp/CoreServerServiceImplTest/rhq-agent"); AgentRegistrationResults aResults = service.registerAgent(aReq); assert aResults != null : "got null results"; persistedAgentInstall = agentManager.getAgentInstallByAgentName(sm.getOverlord(), aReq.getName()); assert persistedAgentInstall != null : "the new agent info is missing"; assert persistedAgentInstall.getAgentName().equals(aReq.getName()); assert persistedAgentInstall.getInstallLocation().equals("/tmp/CoreServerServiceImplTest/rhq-agent"); assert persistedAgentInstall.getSshHost().equals("CoreServerServiceImpl-SshHost"); assert persistedAgentInstall.getSshPort().equals(44); assert persistedAgentInstall.getSshUsername().equals("CoreServerServiceImpl-SshUsername"); assert persistedAgentInstall.getSshPassword().equals("CoreServerServiceImpl-SshPassword"); Agent doomed = agentManager.getAgentByName(aReq.getName()); agentManager.deleteAgent(doomed); persistedAgentInstall = agentManager.getAgentInstallByAgentName(sm.getOverlord(), aReq.getName()); assert persistedAgentInstall == null : "the agent info should have been deleted"; } private void buildFakeAgentJar(File binaryContents, File agentBinaryFile) throws FileNotFoundException, IOException { Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "54321"); JarOutputStream target = new JarOutputStream(new FileOutputStream(agentBinaryFile), manifest); //include the file passed in as contents of the jar. BufferedInputStream in = null; try { JarEntry entry = new JarEntry(binaryContents.getName()); entry.setTime(binaryContents.lastModified()); target.putNextEntry(entry); in = new BufferedInputStream(new FileInputStream(binaryContents)); byte[] buffer = new byte[1024]; while (true) { int count = in.read(buffer); if (count == -1) break; target.write(buffer, 0, count); } target.closeEntry(); } finally { if (in != null) in.close(); } target.close(); } private class DummyCoreServerTweaked extends DummyCoreServer { private String version; private String build; @Override public String getVersion() { return this.version; } @Override public String getBuildNumber() { return this.build; } public DummyCoreServerTweaked(String version, String build) { this.version = version; this.build = build; } } private AgentRegistrationRequest createRequest(String name, String address, int port, String token) { return createRequest(name, address, port, token, "12345", "/tmp/CoreServerServiceImplTest/rhq-agent"); } private AgentRegistrationRequest createRequest(String name, String address, int port, String token, String installId, String installLocation) { return new AgentRegistrationRequest(name, address, port, "socket://" + address + ":" + port + "/?rhq.communications.connector.rhqtype=agent", true, token, agentVersion, installId, installLocation); } private String prefixName(String name) { return TEST_AGENT_NAME_PREFIX + name; } private void debugPrintThrowable(Throwable t) { if (true) { System.out.println(ThrowableUtil.getAllMessages(t)); } } interface DummyCoreServerMBean extends CoreServerMBean { }; class DummyCoreServer implements DummyCoreServerMBean { @Override public String getVersion() { return null; } @Override public String getBuildNumber() { return null; } @Override public Date getBootTime() { return null; } @Override public File getInstallDir() { return null; } @Override public File getJBossServerHomeDir() { return new File(getTempDir(), "CoreServerServiceImplTest"); } @Override public File getJBossServerDataDir() { return new File(getTempDir(), "CoreServerServiceImplTest"); } @Override public File getJBossServerTempDir() { return new File(getTempDir(), "CoreServerServiceImplTest"); } @Override public File getEarDeploymentDir() { return new File(getTempDir(), "CoreServerServiceImplTest"); } @Override public ProductInfo getProductInfo() { return null; } } }