/* * JBoss, Home of Professional Open Source. * Copyright 2013, 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.subsystem.test; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.INCLUDE_DEFAULTS; 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_TRANSFORMED_RESOURCE_OPERATION; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUBSYSTEM; import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.Map; import java.util.Properties; import org.jboss.as.controller.ModelController; import org.jboss.as.controller.ModelVersion; import org.jboss.as.controller.OperationFailedException; import org.jboss.as.controller.PathAddress; import org.jboss.as.controller.PathElement; import org.jboss.as.controller.extension.ExtensionRegistry; import org.jboss.as.controller.operations.common.Util; import org.jboss.as.controller.operations.validation.OperationValidator; import org.jboss.as.controller.registry.ManagementResourceRegistration; import org.jboss.as.controller.transform.OperationResultTransformer; import org.jboss.as.controller.transform.OperationTransformer; import org.jboss.as.controller.transform.OperationTransformer.TransformedOperation; import org.jboss.as.controller.transform.TransformationContext; import org.jboss.as.controller.transform.TransformationTarget; import org.jboss.as.controller.transform.TransformationTargetImpl; import org.jboss.as.controller.transform.TransformerOperationAttachment; import org.jboss.as.controller.transform.Transformers; import org.jboss.as.model.test.ModelTestModelControllerService; import org.jboss.as.model.test.ModelTestUtils; import org.jboss.as.model.test.StringConfigurationPersister; import org.jboss.as.server.mgmt.ManagementWorkerService; import org.jboss.as.version.Version; import org.jboss.dmr.ModelNode; import org.jboss.msc.service.ServiceContainer; import org.xnio.IoUtils; /** * * @author <a href="kabir.khan@jboss.com">Kabir Khan</a> */ class MainKernelServicesImpl extends AbstractKernelServicesImpl { private Class<?> testClass; private static final ModelVersion CURRENT_CORE_VERSION = ModelVersion.create(Version.MANAGEMENT_MAJOR_VERSION, Version.MANAGEMENT_MINOR_VERSION, Version.MANAGEMENT_MICRO_VERSION); protected MainKernelServicesImpl(ServiceContainer container, ModelTestModelControllerService controllerService, StringConfigurationPersister persister, ManagementResourceRegistration rootRegistration, OperationValidator operationValidator, String mainSubsystemName, ExtensionRegistry extensionRegistry, ModelVersion legacyModelVersion, boolean successfulBoot, Throwable bootError, boolean registerTransformers, Class<?> testClass) { super(container, controllerService, persister, rootRegistration, operationValidator, mainSubsystemName, extensionRegistry, legacyModelVersion, successfulBoot, bootError, registerTransformers); this.testClass = testClass; //add mgmt worker ManagementWorkerService.installService(container.subTarget()); } /** * Transforms an operation in the main controller to the format expected by the model controller containing * the legacy subsystem * * @param modelVersion the subsystem model version of the legacy subsystem model controller * @param operation the operation to transform * @return the transformed operation * @throws IllegalStateException if this is not the test's main model controller */ public TransformedOperation transformOperation(ModelVersion modelVersion, ModelNode operation) throws OperationFailedException { return transformOperation(modelVersion, operation, null); } public TransformedOperation transformOperation(ModelVersion modelVersion, ModelNode operation, TransformerOperationAttachment attachment) throws OperationFailedException { checkIsMainController(); PathElement pathElement = PathElement.pathElement(SUBSYSTEM, mainSubsystemName); PathAddress opAddr = PathAddress.pathAddress(operation.get(OP_ADDR)); // Composite operations have no address if ((opAddr.size() > 0 && opAddr.getElement(0).equals(pathElement)) || operation.get(OP).asString().equals(COMPOSITE)) { final Map<PathAddress, ModelVersion> subsystem = Collections.singletonMap(PathAddress.EMPTY_ADDRESS.append(pathElement), modelVersion); final TransformationTarget transformationTarget = TransformationTargetImpl.create(null, extensionRegistry.getTransformerRegistry(), getCoreModelVersionByLegacyModelVersion(modelVersion), subsystem, TransformationTarget.TransformationTargetType.SERVER); final Transformers transformers = Transformers.Factory.create(transformationTarget); final TransformationContext transformationContext = createTransformationContext(transformationTarget, attachment); return transformers.transformOperation(transformationContext, operation); } return new OperationTransformer.TransformedOperation(operation, OperationResultTransformer.ORIGINAL_RESULT); } /** * Transforms the model to the legacy subsystem model version * @param modelVersion the target legacy subsystem model version * @return the transformed model * @throws IllegalStateException if this is not the test's main model controller */ @Override public ModelNode readTransformedModel(ModelVersion modelVersion, boolean includeDefaults) { getLegacyServices(modelVersion);//Checks we are the main controller ModelNode op = new ModelNode(); op.get(OP).set(READ_TRANSFORMED_RESOURCE_OPERATION); op.get(OP_ADDR).set(PathAddress.EMPTY_ADDRESS.toModelNode()); op.get(SUBSYSTEM).set(mainSubsystemName); op.get(INCLUDE_DEFAULTS).set(includeDefaults); ModelNode response = internalExecute(op, new ReadTransformedResourceOperation(getTransformersRegistry(), getCoreModelVersionByLegacyModelVersion(modelVersion), modelVersion)); return ModelTestUtils.checkResultAndGetContents(response); } /** * Execute an operation in the controller containg the passed in version of the subsystem. * The operation and results will be translated from the format for the main controller to the * legacy controller's format. * * @param modelVersion the subsystem model version of the legacy subsystem model controller * @param op the operation for the main controller * @throws IllegalStateException if this is not the test's main model controller * @throws IllegalStateException if there is no legacy controller containing the version of the subsystem */ public ModelNode executeOperation(final ModelVersion modelVersion, final TransformedOperation op) { KernelServices legacy = getLegacyServices(modelVersion); ModelNode result = new ModelNode(); if (op.getTransformedOperation() != null) { result = legacy.executeOperation(op.getTransformedOperation(), new ModelController.OperationTransactionControl() { @Override public void operationPrepared(ModelController.OperationTransaction transaction, ModelNode result) { if(op.rejectOperation(result)) { transaction.rollback(); } else { transaction.commit(); } } }); // TODO this still does not really model the way rejection is handled in the domain if(op.rejectOperation(result)) { final ModelNode newResponse = new ModelNode(); newResponse.get(OUTCOME).set(FAILED); newResponse.get(FAILURE_DESCRIPTION).set(op.getFailureDescription()); return newResponse; } } OperationResultTransformer resultTransformer = op.getResultTransformer(); if (resultTransformer != null) { result = resultTransformer.transformResult(result); } return result; } @Override public Class<?> getTestClass() { return testClass; } @Override public TransformerOperationAttachment executeAndGrabTransformerAttachment(ModelNode op) { try { ModelNode wrapper = Util.createEmptyOperation(TransformerAttachmentGrabber.DESC.getName(), PathAddress.EMPTY_ADDRESS); wrapper.get(VALUE).set(op); ModelTestUtils.checkOutcome(executeOperation(wrapper)); return TransformerAttachmentGrabber.getAttachment(); } finally { TransformerAttachmentGrabber.clear(); } } @Override public TransformedOperation executeInMainAndGetTheTransformedOperation(ModelNode op, ModelVersion modelVersion) { try { ModelNode wrapper = Util.createEmptyOperation(TransformerAttachmentGrabber.DESC.getName(), PathAddress.EMPTY_ADDRESS); wrapper.get(VALUE).set(op); ModelTestUtils.checkOutcome(executeOperation(wrapper)); try { return transformOperation(modelVersion, op, TransformerAttachmentGrabber.getAttachment()); } catch (OperationFailedException e) { throw new RuntimeException(e); } } finally { TransformerAttachmentGrabber.clear(); } } private ModelVersion getCoreModelVersionByLegacyModelVersion(ModelVersion legacyModelVersion) { //The reason the core model version is important is that is used to know if the ignored slave resources are known on the host or not //e.g 7.2.x uses core model version >= 1.4.0 and so we know which resources are ignored //7.1.x uses core model version <= 1.4.0 and so we have no idea which resources are ignored //This is important for example in RejectExpressionValuesTransformer if (System.getProperty("jboss.test.core.model.version.override") != null) { return ModelVersion.fromString(System.getProperty("jboss.test.core.model.version.override")); } ModelVersion coreModelVersion = KnownVersions.getCoreModelVersionForSubsystemVersion(mainSubsystemName, legacyModelVersion); if (coreModelVersion != null) { return coreModelVersion; } String fileName = mainSubsystemName + "-versions-to-as-versions.properties"; InputStream in = this.getClass().getResourceAsStream("/" + fileName); if (in == null) { // throw new IllegalArgumentException("Version " + legacyModelVersion + " of " + mainSubsystemName + " is not a known version. Please add it to " + // KnownVersions.class.getName() + ". Or if that is not possible, " + // "include a src/test/resources/" + fileName + // " file, which maps AS versions to model versions. E.g.:\n1.1.0=7.1.2\n1.2.0=7.1.3"); // Use current return CURRENT_CORE_VERSION; } Properties props = new Properties(); try { props.load(in); } catch (IOException e) { throw new RuntimeException(e); } finally { IoUtils.safeClose(in); } String asVersion = (String)props.get(legacyModelVersion.toString()); if (asVersion == null) { // throw new IllegalArgumentException("src/test/resources/" + fileName + // " does not contain an AS mapping for modelversion + " + // legacyModelVersion + "'. It needs to map AS versions to model versions. E.g.:\n1.1.0=7.1.2\n1.2.0=7.1.3"); // Use current return CURRENT_CORE_VERSION; } coreModelVersion = KnownVersions.AS_CORE_MODEL_VERSION_BY_AS_VERSION.get(asVersion); if (coreModelVersion == null) { // throw new IllegalArgumentException("Unknown AS version '" + asVersion + "' determined from src/test/resources/" + fileName + // ". Known AS versions are " + KnownVersions.AS_CORE_MODEL_VERSION_BY_AS_VERSION.keySet()); // Use current coreModelVersion = CURRENT_CORE_VERSION; } return coreModelVersion; } }