Package org.jboss.as.server.manager

Source Code of org.jboss.as.server.manager.ManagedServer$GetServerModelRequest

/*
* JBoss, Home of Professional Open Source.
* Copyright 2010, 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.server.manager;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import org.jboss.as.model.AbstractServerModelUpdate;
import org.jboss.as.model.DomainModel;
import org.jboss.as.model.Element;
import org.jboss.as.model.HostModel;
import org.jboss.as.model.JvmElement;
import org.jboss.as.model.PropertiesElement;
import org.jboss.as.model.ServerElement;
import org.jboss.as.model.ServerFactory;
import org.jboss.as.model.ServerGroupElement;
import org.jboss.as.model.ServerModel;
import org.jboss.as.model.UpdateResultHandlerResponse;
import org.jboss.as.process.ProcessManagerClient;
import org.jboss.as.protocol.Connection;
import org.jboss.as.protocol.ProtocolUtils;
import static org.jboss.as.protocol.ProtocolUtils.expectHeader;
import static org.jboss.as.protocol.ProtocolUtils.unmarshal;
import org.jboss.as.protocol.mgmt.ManagementRequest;
import org.jboss.as.protocol.mgmt.ManagementRequestConnectionStrategy;
import org.jboss.as.server.ServerController;
import org.jboss.as.server.ServerEnvironment;
import org.jboss.as.server.ServerManagerClient;
import org.jboss.as.server.ServerManagerConnectionService;
import org.jboss.as.server.ServerStartTask;
import org.jboss.as.server.ServerState;
import org.jboss.as.server.mgmt.domain.DomainServerProtocol;
import org.jboss.marshalling.Marshaller;
import org.jboss.marshalling.MarshallerFactory;
import org.jboss.marshalling.Marshalling;
import static org.jboss.marshalling.Marshalling.createByteInput;
import static org.jboss.marshalling.Marshalling.createByteOutput;
import org.jboss.marshalling.MarshallingConfiguration;
import org.jboss.marshalling.ModularClassTable;
import org.jboss.marshalling.Unmarshaller;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoadException;
import org.jboss.msc.service.BatchBuilder;
import org.jboss.msc.service.ServiceActivator;
import org.jboss.msc.service.ServiceActivatorContext;
import org.jboss.msc.service.ServiceController;

/**
* Represents a managed server.
*
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
* @author <a href="mailto:kabir.khan@jboss.com">Kabir Khan</a>
* @author Brian Stansberry
*/
public final class ManagedServer {
    private static final MarshallerFactory MARSHALLER_FACTORY;
    private static final MarshallingConfiguration CONFIG;
    static {
        try {
            MARSHALLER_FACTORY = Marshalling.getMarshallerFactory("river", Module.getModuleFromDefaultLoader(ModuleIdentifier.fromString("org.jboss.marshalling.river")).getClassLoader());
        } catch (ModuleLoadException e) {
            throw new RuntimeException(e);
        }
        final MarshallingConfiguration config = new MarshallingConfiguration();
        config.setVersion(2);
        config.setClassTable(ModularClassTable.getInstance());
        CONFIG = config;
    }

    /**
     * Prefix applied to a server's name to create it's process name.
     */
    static final String SERVER_PROCESS_NAME_PREFIX = "Server:";

    public static String getServerProcessName(String serverName) {
        return SERVER_PROCESS_NAME_PREFIX + serverName;
    }

    private final String serverName;
    private final String serverProcessName;
    private final Map<String, String> systemProperties;
    private final JvmElement jvmElement;
    private final ServerManagerEnvironment environment;
    private final int portOffset;
    private final ProcessManagerClient processManagerClient;
    private final AtomicInteger respawnCount = new AtomicInteger();
    private final List<AbstractServerModelUpdate<?>> updateList = new ArrayList<AbstractServerModelUpdate<?>>();
    private final InetSocketAddress managementSocket;
    private volatile ServerState state;
    private Connection serverManagementConnection;

    private final byte[] authKey;

    public ManagedServer(final String serverName, final DomainModel domainModel, final HostModel hostModel,
            final ServerManagerEnvironment environment, final ProcessManagerClient processManagerClient,
            final InetSocketAddress managementSocket) {
        assert domainModel != null : "domainModel is null";
        assert hostModel   != null : "hostModel is null";
        assert serverName  != null : "serverName is null";
        assert environment != null : "environment is null";
        assert processManagerClient != null : "processManagerSlave is null";
        assert managementSocket != null : "managementSocket is null";

        final byte[] authKey = new byte[16];
        // TODO: use a RNG with a secure seed
        new Random().nextBytes(authKey);
        this.authKey = authKey;

        this.serverName = serverName;
        this.serverProcessName = getServerProcessName(serverName);
        this.environment = environment;
        this.processManagerClient = processManagerClient;
        this.managementSocket = managementSocket;

        ServerFactory.combine(domainModel, hostModel, serverName, updateList);

        ServerElement server = hostModel.getServer(serverName);
        if (server == null)
            throw new IllegalStateException("Server " + serverName + " is not listed in Host");

        String serverGroupName = server.getServerGroup();
        ServerGroupElement serverGroup = domainModel.getServerGroup(serverGroupName);
        if (serverGroup == null)
            throw new IllegalStateException("Server group" + serverGroupName + " is not listed in Domain");

        this.portOffset = server.getSocketBindingGroupName() == null ? serverGroup.getSocketBindingPortOffset() : server.getSocketBindingPortOffset();

        JvmElement serverVM = server.getJvm();
        String serverVMName = serverVM != null ? serverVM.getName() : null;

        JvmElement groupVM = serverGroup.getJvm();
        String groupVMName = groupVM != null ? groupVM.getName() : null;

        String ourVMName = serverVMName != null ? serverVMName : groupVMName;
        if (ourVMName == null) {
            throw new IllegalStateException("Neither " + Element.SERVER_GROUP.getLocalName() +
                    " nor " + Element.SERVER.getLocalName() + " has declared a JVM configuration; one or the other must");
        }

        if (!ourVMName.equals(groupVMName)) {
            // the server setting replaced the group, so ignore group
            groupVM = null;
        }
        JvmElement hostVM = hostModel.getJvm(ourVMName);

        jvmElement = new JvmElement(groupVM, hostVM, serverVM);

        Map<String, String> properties = new HashMap<String, String>();
        properties.putAll(domainModel.getSystemProperties().getProperties());
        properties.putAll(serverGroup.getSystemProperties().getProperties());
        properties.putAll(hostModel.getSystemProperties().getProperties());
        properties.putAll(server.getSystemProperties().getProperties());
        // TODO remove system properties from JvmElement
        properties.putAll(jvmElement.getSystemProperties().getProperties());
        addStandardProperties(properties);

        this.systemProperties = properties;

        this.state = ServerState.BOOTING;

    }

    public ServerState getState() {
        return state;
    }

    void setState(ServerState state) {
        this.state = state;
    }

    int incrementAndGetRespawnCount() {
        return respawnCount.incrementAndGet();
    }

    void resetRespawnCount() {
        respawnCount.set(0);
    }

    String getServerProcessName() {
        return serverProcessName;
    }

    String getServerName() {
        return serverName;
    }

    List<AbstractServerModelUpdate<?>> getUpdates() {
        return new ArrayList<AbstractServerModelUpdate<?>>(updateList);
    }

    List<String> getServerLaunchCommand() {
        List<String> command = new ArrayList<String>();

//      if (false) {
//          // Example: run at high priority on *NIX
//          args.add("/usr/bin/nice");
//          args.add("-n");
//          args.add("-10");
//      }
//      if (false) {
//          // Example: run only on processors 1-4 on Linux
//          args.add("/usr/bin/taskset");
//          args.add("0x0000000F");
//      }

        command.add(getJavaCommand());

        JvmOptionsBuilderFactory.getInstance().addOptions(jvmElement, command);

        for (Map.Entry<String, String> prop : systemProperties.entrySet()) {
            StringBuilder sb = new StringBuilder("-D");
            sb.append(prop.getKey());
            sb.append('=');
            sb.append(prop.getValue() == null ? "true" : prop.getValue());
            command.add(sb.toString());
        }

        command.add("-Dorg.jboss.boot.log.file=domain/servers/" + serverName + "/log/boot.log");
        // TODO: make this better
        command.add("-Dlogging.configuration=file:" + new File("").getAbsolutePath() + "/domain/configuration/logging.properties");
        command.add("-jar");
        command.add("jboss-modules.jar");
        command.add("-mp");
        command.add("modules");
        command.add("-logmodule");
        command.add("org.jboss.logmanager");
        command.add("org.jboss.as.server");

        return command;
    }

    Map<String, String> getServerLaunchEnvironment() {
        Map<String, String> env = null;
        PropertiesElement pe = jvmElement.getEnvironmentVariables();
        if (pe != null) {
            env = pe.getProperties();
        }
        else {
            env = Collections.emptyMap();
        }
        return env;
    }

    public void addServerProcess() throws IOException {
        List<String> command = getServerLaunchCommand();

        Map<String, String> env = getServerLaunchEnvironment();

        //Add to process manager
        processManagerClient.addProcess(serverProcessName, authKey, command.toArray(new String[command.size()]), environment.getHomeDir().getAbsolutePath(), env);
    }

    public void startServerProcess() throws IOException {

        setState(ServerState.BOOTING);


        processManagerClient.startProcess(serverProcessName);
        ServiceActivator serverManagerCommActivator = new ServerManagerCommServiceActivator(managementSocket);
        ServerStartTask startTask = new ServerStartTask(serverName, portOffset, Collections.<ServiceActivator>singletonList(serverManagerCommActivator), updateList);
        final Marshaller marshaller = MARSHALLER_FACTORY.createMarshaller(CONFIG);
        final OutputStream os = processManagerClient.sendStdin(serverProcessName);
        marshaller.start(Marshalling.createByteOutput(os));
        marshaller.writeObject(startTask);
        marshaller.finish();
        marshaller.close();
        os.close();

        setState(ServerState.STARTING);
    }

    public void stopServerProcess() throws IOException {
        processManagerClient.stopProcess(serverProcessName);
    }

    public void removeServerProcess() throws IOException {
        processManagerClient.removeProcess(serverProcessName);
    }

    public List<UpdateResultHandlerResponse<?>> applyUpdates(final List<AbstractServerModelUpdate<?>> updates, final boolean allowOverallRollback) {

        if(serverManagementConnection == null) {
            Exception e = new IllegalStateException("Updates can not be applied to a managed server without a management connection");
            UpdateResultHandlerResponse<?> urhr = UpdateResultHandlerResponse.createFailureResponse(e);
            List<UpdateResultHandlerResponse<?>> result = new ArrayList<UpdateResultHandlerResponse<?>>(updates.size());
            for (int i = 0; i < updates.size(); i++) {
                result.add(urhr);
            }
            return result;
        }

        try {
            return new ApplyUpdatesRequest(updates, allowOverallRollback).executeForResult(new ManagementRequestConnectionStrategy.ExistingConnectionStrategy(serverManagementConnection));
        } catch (Exception e) {
            UpdateResultHandlerResponse<?> urhr = UpdateResultHandlerResponse.createFailureResponse(e);
            List<UpdateResultHandlerResponse<?>> result = new ArrayList<UpdateResultHandlerResponse<?>>(updates.size());
            for (int i = 0; i < updates.size(); i++) {
                result.add(urhr);
            }
            return result;
        }
    }

    public void gracefulShutdown(long timeout) throws IOException {
        // FIXME implement gracefulShutdown RPC
        throw new UnsupportedOperationException("ServerManager to Server RPC is not implemented");
    }

    public ServerModel getServerModel() {
        try {
            return new GetServerModelRequest().executeForResult(new ManagementRequestConnectionStrategy.ExistingConnectionStrategy(serverManagementConnection));
        } catch (Exception e) {
            throw new RuntimeException("Failed to get ServerModel from server [" + serverName + "]", e);
        }
    }

    private String getJavaCommand() {
        String javaHome = jvmElement.getJavaHome();
        if (javaHome == null) { // TODO should this be possible?
            if(environment.getDefaultJVM() != null) {
                return environment.getDefaultJVM().getAbsolutePath();
            }
            return "java"; // hope for the best
        }

        File f = new File(javaHome);
        f = new File(f, "bin");
        f = new File (f, "java");
        return f.getAbsolutePath();
    }

    public void setServerManagementConnection(Connection serverManagementConnection) {
        this.serverManagementConnection = serverManagementConnection;
        // FIXME this isn't really correct; just means the server started
        // enough to connect
        setState(ServerState.STARTED);
    }

    /**
     * Equivalent to default JAVA_OPTS in < AS 7 run.conf file
     *
     * TODO externalize this somewhere if doing this at all is the right thing
     *
     * @param sysProps
     */
    private void addStandardProperties(Map<String, String> sysProps) {
        //
        if (!sysProps.containsKey("sun.rmi.dgc.client.gcInterval")) {
            sysProps.put("sun.rmi.dgc.client.gcInterval","3600000");
        }
        if (!sysProps.containsKey("sun.rmi.dgc.server.gcInterval")) {
            sysProps.put("sun.rmi.dgc.server.gcInterval","3600000");
        }

        sysProps.put(ServerManagerEnvironment.HOME_DIR, environment.getHomeDir().getAbsolutePath());
        String key = ServerEnvironment.SERVER_BASE_DIR;
        if (sysProps.get(key) == null) {
            File serverBaseDir = new File(environment.getDomainServersDir(), serverName);
            sysProps.put(key, serverBaseDir.getAbsolutePath());
        }
        // Servers should use the server manager's deployment content repo
        key = ServerEnvironment.SERVER_DEPLOY_DIR;
        if (sysProps.get(key) == null) {
            File serverDeploymentDir = environment.getDomainDeploymentDir();
            sysProps.put(key, serverDeploymentDir.getAbsolutePath());
        }

        key = ServerEnvironment.SERVER_SYSTEM_DEPLOY_DIR;
        if (sysProps.get(key) == null) {
            File serverDeploymentDir = environment.getDomainSystemDeploymentDir();
            sysProps.put(key, serverDeploymentDir.getAbsolutePath());
        }
    }

    private static class ServerManagerCommServiceActivator implements ServiceActivator, Serializable {
        private final InetSocketAddress managementSocket;

        private ServerManagerCommServiceActivator(InetSocketAddress managementSocket) {
            this.managementSocket = managementSocket;
        }

        private static final long serialVersionUID = 2522252040771977214L;

        public void activate(final ServiceActivatorContext serviceActivatorContext) {
            final BatchBuilder batchBuilder = serviceActivatorContext.getBatchBuilder();

            final ServerManagerConnectionService smConnection = new ServerManagerConnectionService();
            batchBuilder.addService(ServerManagerConnectionService.SERVICE_NAME, smConnection)
                .addInjection(smConnection.getSmAddressInjector(), managementSocket)
                .setInitialMode(ServiceController.Mode.ACTIVE);

            final ServerManagerClient client = new ServerManagerClient();
            batchBuilder.addService(ServerManagerClient.SERVICE_NAME, client)
                .addDependency(ServerManagerConnectionService.SERVICE_NAME, Connection.class, client.getSmConnectionInjector())
                .addDependency(ServerController.SERVICE_NAME, ServerController.class, client.getServerControllerInjector())
                .setInitialMode(ServiceController.Mode.ACTIVE);
        }
    }

    private static class ApplyUpdatesRequest extends ManagementRequest<List<UpdateResultHandlerResponse<?>>> {
        private final List<AbstractServerModelUpdate<?>> updates;
        private final boolean allowOverallRollback;

        private ApplyUpdatesRequest(final List<AbstractServerModelUpdate<?>> updates, final boolean allowOverallRollback) {
            this.updates = updates;
            this.allowOverallRollback = allowOverallRollback;
        }

        @Override
        protected byte getHandlerId() {
            return DomainServerProtocol.SERVER_TO_SERVER_MANAGER_OPERATION;
        }

        @Override
        protected byte getRequestCode() {
            return DomainServerProtocol.SERVER_MODEL_UPDATES_REQUEST;
        }

        @Override
        protected byte getResponseCode() {
            return DomainServerProtocol.SERVER_MODEL_UPDATES_RESPONSE;
        }

        @Override
        protected void sendRequest(final int protocolVersion, final OutputStream output) throws IOException {
            final Marshaller marshaller = getMarshaller();
            marshaller.start(createByteOutput(output));
            marshaller.writeByte(DomainServerProtocol.PARAM_ALLOW_ROLLBACK);
            marshaller.writeBoolean(allowOverallRollback);
            marshaller.writeByte(DomainServerProtocol.PARAM_SERVER_MODEL_UPDATE_COUNT);
            marshaller.writeInt(updates.size());
            for (AbstractServerModelUpdate<?> update : updates) {
                marshaller.writeByte(DomainServerProtocol.PARAM_SERVER_MODEL_UPDATE);
                marshaller.writeObject(update);
            }
            marshaller.finish();
        }

        @Override
        protected final List<UpdateResultHandlerResponse<?>> receiveResponse(final InputStream input) throws IOException {
            final Unmarshaller unmarshaller = getUnmarshaller();
            unmarshaller.start(createByteInput(input));
            expectHeader(unmarshaller, DomainServerProtocol.PARAM_SERVER_MODEL_UPDATE_RESPONSE_COUNT);
            final int updateCount = unmarshaller.readInt();
            final List<UpdateResultHandlerResponse<?>> results = new ArrayList<UpdateResultHandlerResponse<?>>(updateCount);
            for (int i = 0; i < updateCount; i++) {
                expectHeader(unmarshaller, DomainServerProtocol.PARAM_SERVER_MODEL_UPDATE_RESPONSE);
                UpdateResultHandlerResponse<?> updateResult = unmarshal(unmarshaller, UpdateResultHandlerResponse.class);
                results.add(updateResult);
            }
            unmarshaller.finish();
            return results;
        }
    }

    private class GetServerModelRequest extends ManagementRequest<ServerModel> {

        @Override
        protected byte getHandlerId() {
            return DomainServerProtocol.SERVER_TO_SERVER_MANAGER_OPERATION;
        }

        @Override
        protected byte getRequestCode() {
            return DomainServerProtocol.GET_SERVER_MODEL_REQUEST;
        }

        @Override
        protected byte getResponseCode() {
            return DomainServerProtocol.GET_SERVER_MODEL_RESPONSE;
        }

        @Override
        protected final ServerModel receiveResponse(final InputStream input) throws IOException {
            final Unmarshaller unmarshaller = getUnmarshaller();
            unmarshaller.start(createByteInput(input));
            expectHeader(unmarshaller, DomainServerProtocol.RETURN_SERVER_MODEL);
            ServerModel serverModel = unmarshal(unmarshaller, ServerModel.class);
            unmarshaller.finish();
            return serverModel;
        }
    }

    private static Marshaller getMarshaller() throws IOException {
        return ProtocolUtils.getMarshaller(ProtocolUtils.MODULAR_CONFIG);
    }

    private static Unmarshaller getUnmarshaller() throws IOException {
        return ProtocolUtils.getUnmarshaller(ProtocolUtils.MODULAR_CONFIG);
    }
}
TOP

Related Classes of org.jboss.as.server.manager.ManagedServer$GetServerModelRequest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.