/*
* JBoss, Home of Professional Open Source.
* Copyright 2011, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.test.integration.domain.suites;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADD;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONTENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DEPLOYMENT;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DOMAIN_CONTROLLER;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HASH;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.IGNORE_UNUSED_CONFIG;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INPUT_STREAM_INDEX;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_ATTRIBUTE_OPERATION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_RESOURCE_OPERATION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.REMOTE;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESTART_SERVERS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_GROUP;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STEPS;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.jboss.as.controller.HashUtil;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.client.ModelControllerClient;
import org.jboss.as.controller.client.Operation;
import org.jboss.as.controller.client.OperationBuilder;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.test.integration.domain.management.util.DomainLifecycleUtil;
import org.jboss.as.test.integration.domain.management.util.DomainTestSupport;
import org.jboss.as.test.integration.domain.management.util.DomainTestUtils;
import org.jboss.as.test.integration.management.util.MgmtOperationException;
import org.jboss.dmr.ModelNode;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Test of slave hosts ability to ignore ops sent by master for certain resources (AS7-3174).
*
* @author Brian Stansberry (c) 2011 Red Hat Inc.
*/
public class IgnoredResourcesTestCase {
private static DomainTestSupport testSupport;
private static DomainLifecycleUtil domainMasterLifecycleUtil;
private static DomainLifecycleUtil domainSlaveLifecycleUtil;
@BeforeClass
public static void setupDomain() throws Exception {
testSupport = DomainTestSuite.createSupport(IgnoredResourcesTestCase.class.getSimpleName());
domainMasterLifecycleUtil = testSupport.getDomainMasterLifecycleUtil();
domainSlaveLifecycleUtil = testSupport.getDomainSlaveLifecycleUtil();
final ModelNode slaveModel = DomainTestUtils.executeForResult(Util.getReadAttributeOperation(PathAddress.pathAddress(HOST, "slave"), DOMAIN_CONTROLLER),
domainMasterLifecycleUtil.getDomainClient()).get(REMOTE);
slaveModel.get(IGNORE_UNUSED_CONFIG).set(false);
DomainTestUtils.executeForResult(Util.createEmptyOperation("remove-remote-domain-controller", PathAddress.pathAddress(HOST, "slave")), domainSlaveLifecycleUtil.getDomainClient());
ModelNode writeRemoteDc = Util.createEmptyOperation("write-remote-domain-controller", PathAddress.pathAddress(HOST, "slave"));
for (String key : slaveModel.keys()) {
writeRemoteDc.get(key).set(slaveModel.get(key));
}
DomainTestUtils.executeForResult(writeRemoteDc, domainSlaveLifecycleUtil.getDomainClient());
ModelNode restartSlave = Util.createEmptyOperation("reload", PathAddress.pathAddress(HOST, "slave"));
restartSlave.get(RESTART_SERVERS).set(false);
domainSlaveLifecycleUtil.executeAwaitConnectionClosed(restartSlave);
domainSlaveLifecycleUtil.connect();
domainSlaveLifecycleUtil.awaitHostController(System.currentTimeMillis());
domainMasterLifecycleUtil = testSupport.getDomainMasterLifecycleUtil();
domainSlaveLifecycleUtil = testSupport.getDomainSlaveLifecycleUtil();
ModelNode slaveIgnore = Util.createEmptyOperation(READ_RESOURCE_OPERATION, PathAddress.pathAddress(HOST, "slave"));
ModelNode result = DomainTestUtils.executeForResult(slaveIgnore, domainSlaveLifecycleUtil.getDomainClient());
// make sure that ignore-unused-configuration is false
Assert.assertFalse(result.get(DOMAIN_CONTROLLER).get(REMOTE).get(IGNORE_UNUSED_CONFIG).asBoolean());
}
@AfterClass
public static void tearDownDomain() throws Exception {
// reset ignore-unused-configuration back to true, and reload
final ModelNode slaveModel = DomainTestUtils.executeForResult(Util.getReadAttributeOperation(PathAddress.pathAddress(HOST, "slave"), DOMAIN_CONTROLLER),
domainMasterLifecycleUtil.getDomainClient()).get(REMOTE);
slaveModel.get(IGNORE_UNUSED_CONFIG).set(true);
DomainTestUtils.executeForResult(Util.createEmptyOperation("remove-remote-domain-controller", PathAddress.pathAddress(HOST, "slave")), domainSlaveLifecycleUtil.getDomainClient());
ModelNode writeRemoteDc = Util.createEmptyOperation("write-remote-domain-controller", PathAddress.pathAddress(HOST, "slave"));
for (String key : slaveModel.keys()) {
writeRemoteDc.get(key).set(slaveModel.get(key));
}
DomainTestUtils.executeForResult(writeRemoteDc, domainSlaveLifecycleUtil.getDomainClient());
ModelNode restartSlave = Util.createEmptyOperation("reload", PathAddress.pathAddress(HOST, "slave"));
restartSlave.get(RESTART_SERVERS).set(false);
domainSlaveLifecycleUtil.executeAwaitConnectionClosed(restartSlave);
domainSlaveLifecycleUtil.connect();
domainSlaveLifecycleUtil.awaitHostController(System.currentTimeMillis());
domainMasterLifecycleUtil = testSupport.getDomainMasterLifecycleUtil();
domainSlaveLifecycleUtil = testSupport.getDomainSlaveLifecycleUtil();
ModelNode slaveIgnore = Util.createEmptyOperation(READ_RESOURCE_OPERATION, PathAddress.pathAddress(HOST, "slave"));
ModelNode result = DomainTestUtils.executeForResult(slaveIgnore, domainSlaveLifecycleUtil.getDomainClient());
// make sure that ignore-unused-configuration is true
Assert.assertTrue(result.get(DOMAIN_CONTROLLER).get(REMOTE).get(IGNORE_UNUSED_CONFIG).asBoolean());
testSupport = null;
domainMasterLifecycleUtil = null;
domainSlaveLifecycleUtil = null;
DomainTestSuite.stopSupport();
}
@Test
public void testProfileIgnored() throws Exception {
ModelNode op = createOpNode(null, "read-children-names");
op.get("child-type").set("profile");
// Sanity check againt domain
ModelNode result = executeOperation(op, domainMasterLifecycleUtil.getDomainClient());
boolean found = false;
for (ModelNode profile : result.asList()) {
if ("ignored".equals(profile.asString())) {
found = true;
break;
}
}
Assert.assertTrue(found);
// Resource should not exist on slave
result = executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("ignored".equals(profile.asString())) {
Assert.fail("found profile 'ignored'");
}
}
// Modify the ignored profile
ModelNode mod = createOpNode("profile=ignored/subsystem=io", "add");
executeOperation(mod, domainMasterLifecycleUtil.getDomainClient());
// Resource still should not exist on slave
result = executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("ignored".equals(profile.asString())) {
Assert.fail("found profile 'ignored'");
}
}
}
@Test
public void testSocketBindingGroupIgnored() throws Exception {
ModelNode op = createOpNode(null, "read-children-names");
op.get("child-type").set("socket-binding-group");
// Sanity check againt domain
ModelNode result = executeOperation(op, domainMasterLifecycleUtil.getDomainClient());
boolean found = false;
for (ModelNode profile : result.asList()) {
if ("ignored".equals(profile.asString())) {
found = true;
break;
}
}
Assert.assertTrue(found);
// Resource should not exist on slave
result = executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("ignored".equals(profile.asString())) {
Assert.fail("found socket-binding-group 'ignored'");
}
}
// Modify the ignored group
ModelNode mod = createOpNode("socket-binding-group=ignored/socket-binding=test", "add");
mod.get("port").set(12345);
executeOperation(mod, domainMasterLifecycleUtil.getDomainClient());
// Resource still should not exist on slave
result = executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("ignored".equals(profile.asString())) {
Assert.fail("found socket-binding-group 'ignored'");
}
}
}
@Test
public void testExtensionIgnored() throws Exception {
ModelNode op = createOpNode(null, "read-children-names");
op.get("child-type").set("extension");
// Sanity check againt domain
ModelNode result = executeOperation(op, domainMasterLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("org.jboss.as.threads".equals(profile.asString())) {
Assert.fail("found extension 'org.jboss.as.threads'");
}
}
// Resource should not exist on slave
result = executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("org.jboss.as.threads".equals(profile.asString())) {
Assert.fail("found extension 'org.jboss.as.threads'");
}
}
// Add the ignored extension
ModelNode mod = createOpNode("extension=org.jboss.as.threads", "add");
executeOperation(mod, domainMasterLifecycleUtil.getDomainClient());
// Resource still should not exist on slave
result = executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("org.jboss.as.threads".equals(profile.asString())) {
Assert.fail("found extension 'org.jboss.as.threads'");
}
}
//do cleanup
executeOperation(createOpNode("extension=org.jboss.as.threads", "remove"), domainMasterLifecycleUtil.getDomainClient());
}
@Test
public void testIgnoreTypeHost() throws IOException {
ModelNode op = createOpNode("core-service=ignored-resources/ignored-resource-type=host", "add");
op.get("wildcard").set(true);
try {
executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
Assert.fail("should not be able to ignore type 'host'");
} catch (MgmtOperationException good) {
//
}
}
@Test
public void testServerGroupIgnored() throws Exception {
final ModelNode op = createOpNode(null, "read-children-names");
op.get("child-type").set("server-group");
final ModelNode result = executeOperation(op, domainSlaveLifecycleUtil.getDomainClient());
for (ModelNode profile : result.asList()) {
if ("minimal".equals(profile.asString())) {
Assert.fail("found server-group 'minimal'");
}
}
}
@Test
public void testDeploymentIgnored() throws Exception {
final JavaArchive archive = ShrinkWrap.create(JavaArchive.class);
archive.add(new StringAsset("test"), "test");
final InputStream is = archive.as(ZipExporter.class).exportAsInputStream();
try {
final ModelNode composite = new ModelNode();
composite.get(OP).set(COMPOSITE);
composite.get(OP_ADDR).setEmptyList();
final ModelNode steps = composite.get(STEPS);
final ModelNode add = steps.add();
add.get(OP).set(ADD);
add.get(OP_ADDR).add(DEPLOYMENT, "test.jar");
add.get(CONTENT).add().get(INPUT_STREAM_INDEX).set(0);
final ModelNode sAdd = steps.add();
sAdd.get(OP).set(ADD);
sAdd.get(OP_ADDR).add(SERVER_GROUP, "minimal").add(DEPLOYMENT, "test.jar");
final Operation operation = OperationBuilder.create(composite).addInputStream(is).build();
final ModelNode result = domainMasterLifecycleUtil.getDomainClient().execute(operation);
Assert.assertEquals(result.asString(), result.get(OUTCOME).asString(), SUCCESS);
final ModelNode ra = new ModelNode();
ra.get(OP).set(READ_ATTRIBUTE_OPERATION);
ra.get(OP_ADDR).add(DEPLOYMENT, "test.jar");
ra.get(NAME).set(CONTENT);
final ModelNode r = DomainTestUtils.executeForResult(ra, domainMasterLifecycleUtil.getDomainClient());
final byte[] hash = r.get(0).get(HASH).asBytes();
Assert.assertTrue(exists(domainMasterLifecycleUtil, hash));
Assert.assertFalse(exists(domainSlaveLifecycleUtil, hash));
} finally {
if (is != null) try {
is.close();
} catch (IOException e) {
// ignored
}
}
}
private static ModelNode createOpNode(String address, String operation) {
ModelNode op = new ModelNode();
// set address
ModelNode list = op.get("address").setEmptyList();
if (address != null) {
String [] pathSegments = address.split("/");
for (String segment : pathSegments) {
String[] elements = segment.split("=");
list.add(elements[0], elements[1]);
}
}
op.get("operation").set(operation);
return op;
}
private ModelNode executeOperation(final ModelNode op, final ModelControllerClient modelControllerClient) throws IOException, MgmtOperationException {
return DomainTestUtils.executeForResult(op, modelControllerClient);
}
static boolean exists(final DomainLifecycleUtil util, final byte[] hash) {
final File home = new File(util.getConfiguration().getDomainDirectory());
// Domain contents
final File data = new File(home, "data");
final File contents = new File(data, "content");
return exists(contents, hash);
}
static boolean exists(final File root, final byte[] hash) {
final String sha1 = HashUtil.bytesToHexString(hash);
final String partA = sha1.substring(0,2);
final String partB = sha1.substring(2);
final File da = new File(root, partA);
final File db = new File(da, partB);
final File content = new File(db, "content");
return content.exists();
}
}