/* * JBoss, Home of Professional Open Source. * Copyright 2015, Red Hat Middleware LLC, 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; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.*; import java.io.IOException; import java.util.Iterator; import java.util.List; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.client.helpers.domain.DomainClient; 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.DomainTestUtils; import org.jboss.as.test.integration.domain.management.util.WildFlyManagedConfiguration; import org.jboss.as.test.integration.management.util.MgmtOperationException; import org.jboss.as.test.shared.TimeoutUtil; import org.jboss.dmr.ModelNode; import org.jboss.dmr.Property; import org.junit.Assert; import org.junit.Test; /** * Checks that the child resources that should be ordered are in fact so on a slave reconnect. * At the moment this is only jgroups protocols. Although we have good tests for the indexed adds * working on reconnect in core, this is here as a sanity that no special describe handler is used * overriding the default mechanism. * * @author Kabir Khan */ public class OrderedChildResourcesTestCase extends BuildConfigurationTestBase { public static final String slaveAddress = System.getProperty("jboss.test.host.slave.address", "127.0.0.1"); private static final int ADJUSTED_SECOND = TimeoutUtil.adjust(1000); @Test public void testOrderedChildResources() throws Exception { final WildFlyManagedConfiguration masterConfig = createConfiguration("domain.xml", "host-master.xml", getClass().getSimpleName()); final DomainLifecycleUtil masterUtils = new DomainLifecycleUtil(masterConfig); final WildFlyManagedConfiguration slaveConfig = createConfiguration("domain.xml", "host-slave.xml", getClass().getSimpleName(), "slave", slaveAddress, 19999); final DomainLifecycleUtil slaveUtils = new DomainLifecycleUtil(slaveConfig); try { masterUtils.start(); slaveUtils.start(); PathAddress jgroupsTcpAddr = PathAddress.pathAddress(PROFILE, "full-ha") .append(SUBSYSTEM, "jgroups") .append("stack", "tcp"); final ModelNode originalMasterStack = readResource(masterUtils.getDomainClient(), jgroupsTcpAddr); originalMasterStack.protect(); final ModelNode originalSlaveStack = readResource(slaveUtils.getDomainClient(), jgroupsTcpAddr); originalSlaveStack.protect(); Assert.assertEquals(originalMasterStack, originalSlaveStack); //FD_ALL is normally in the middle somewhere final String protocolName = "FD_ALL"; int index = -1; ModelNode value = null; Iterator<Property> it = originalMasterStack.get(PROTOCOL).asPropertyList().iterator(); for (int i = 0; it.hasNext(); i++) { Property property = it.next(); if (property.getName().equals(protocolName)) { value = property.getValue(); index = i; break; } } //Make sure that we found the protocol and that it is not at the end Assert.assertTrue(0 <= index); Assert.assertTrue(index < originalMasterStack.get(PROTOCOL).keys().size() - 2); //Remove the protocol DomainTestUtils.executeForResult(Util.createRemoveOperation(jgroupsTcpAddr.append(PROTOCOL, protocolName)), masterUtils.getDomainClient()); //Reload the master into admin-only and re-add the protocol reloadMaster(masterUtils, true); ModelNode add = value.clone(); add.get(OP).set(ADD); add.get(OP_ADDR).set(jgroupsTcpAddr.append(PROTOCOL, protocolName).toModelNode()); add.get(ADD_INDEX).set(index); DomainTestUtils.executeForResult(add, masterUtils.getDomainClient()); //Reload the master into normal mode and check the protocol is in the right place on the slave reloadMaster(masterUtils, false); ModelNode slaveStack = readResource(slaveUtils.getDomainClient(), jgroupsTcpAddr); Assert.assertEquals(originalMasterStack, slaveStack); //Check that :read-operation-description has add-index defined; WFLY-6782 ModelNode rodOp = Util.createOperation(READ_OPERATION_DESCRIPTION_OPERATION, jgroupsTcpAddr.append(PROTOCOL, protocolName)); rodOp.get(NAME).set(ADD); ModelNode result = DomainTestUtils.executeForResult(rodOp, masterUtils.getDomainClient()); Assert.assertTrue(result.get(REQUEST_PROPERTIES).hasDefined(ADD_INDEX)); } finally { try { slaveUtils.stop(); } finally { masterUtils.stop(); } } } private ModelNode readResource(DomainClient client, PathAddress pathAddress) throws IOException, MgmtOperationException { ModelNode rr = Util.createEmptyOperation(READ_RESOURCE_OPERATION, pathAddress); return DomainTestUtils.executeForResult(rr, client); } private void reloadMaster(DomainLifecycleUtil domainMasterLifecycleUtil, boolean adminOnly) throws Exception{ ModelNode restartAdminOnly = Util.createEmptyOperation("reload", PathAddress.pathAddress(HOST, "master")); restartAdminOnly.get("admin-only").set(adminOnly); domainMasterLifecycleUtil.executeAwaitConnectionClosed(restartAdminOnly); domainMasterLifecycleUtil.connect(); domainMasterLifecycleUtil.awaitHostController(System.currentTimeMillis()); if (!adminOnly) { //Wait for the slave to reconnect, look for the slave in the list of hosts long end = System.currentTimeMillis() + 20 * ADJUSTED_SECOND; boolean slaveReconnected = false; do { Thread.sleep(1 * ADJUSTED_SECOND); slaveReconnected = checkSlaveReconnected(domainMasterLifecycleUtil.getDomainClient()); } while (!slaveReconnected && System.currentTimeMillis() < end); } } private boolean checkSlaveReconnected(DomainClient masterClient) throws Exception { ModelNode op = Util.createEmptyOperation(READ_CHILDREN_NAMES_OPERATION, PathAddress.EMPTY_ADDRESS); op.get(CHILD_TYPE).set(HOST); try { ModelNode ret = DomainTestUtils.executeForResult(op, masterClient); List<ModelNode> list = ret.asList(); if (list.size() == 2) { for (ModelNode entry : list) { if ("slave".equals(entry.asString())){ return true; } } } } catch (Exception e) { } return false; } }