/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.core.communication.configuration.internal; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.osgi.framework.BundleContext; import de.rcenvironment.core.communication.api.NodeIdentifierService; import de.rcenvironment.core.communication.common.IdentifierException; import de.rcenvironment.core.communication.common.InstanceNodeId; import de.rcenvironment.core.communication.common.InstanceNodeSessionId; import de.rcenvironment.core.communication.configuration.CommunicationConfiguration; import de.rcenvironment.core.communication.configuration.CommunicationIPFilterConfiguration; import de.rcenvironment.core.communication.configuration.NodeConfigurationService; import de.rcenvironment.core.communication.configuration.SshConnectionsConfiguration; import de.rcenvironment.core.communication.model.InitialNodeInformation; import de.rcenvironment.core.communication.model.NetworkContactPoint; import de.rcenvironment.core.communication.model.impl.InitialNodeInformationImpl; import de.rcenvironment.core.communication.sshconnection.InitialSshConnectionConfig; import de.rcenvironment.core.communication.utils.NetworkContactPointUtils; import de.rcenvironment.core.configuration.ConfigurationSegment; import de.rcenvironment.core.configuration.ConfigurationService; import de.rcenvironment.core.configuration.PersistentSettingsService; import de.rcenvironment.core.utils.common.StringUtils; /** * Default {@link NodeConfigurationService} implementation. * * @author Robert Mischke * @author Sascha Zur */ public class NodeConfigurationServiceImpl implements NodeConfigurationService { // TODO temporary hardcoded default for actual RCE instances; see Mantis #8074 private static final int STARTUP_INITIAL_CONNECT_DELAY_MSEC = 2500; private final List<NetworkContactPoint> serverContactPoints; private final List<NetworkContactPoint> initialNetworkPeers; private InitialNodeInformationImpl localNodeInformation; private CommunicationConfiguration configuration; private SshConnectionsConfiguration sshConfiguration; private ConfigurationService configurationService; private PersistentSettingsService persistentSettingsService; private CommunicationIPFilterConfiguration ipFilterConfiguration; private boolean initialIPFilterConfigLoaded = false; private final Log log = LogFactory.getLog(getClass()); private boolean localNodeIsRelay; private InstanceNodeId localInstanceId; private NodeIdentifierService nodeIdentifierService; private InstanceNodeSessionId localInstanceSessionId; public NodeConfigurationServiceImpl() { serverContactPoints = new ArrayList<NetworkContactPoint>(); initialNetworkPeers = new ArrayList<NetworkContactPoint>(); } @Override public NodeIdentifierService getNodeIdentifierService() { return nodeIdentifierService; } @Override public InstanceNodeSessionId getInstanceNodeSessionId() { return localNodeInformation.getInstanceNodeSessionId(); } @Override @Deprecated public boolean isWorkflowHost() { return configurationService.getIsWorkflowHost(); } @Override public InitialNodeInformation getInitialNodeInformation() { return localNodeInformation; } @Override public List<NetworkContactPoint> getServerContactPoints() { return Collections.unmodifiableList(serverContactPoints); } @Override public List<NetworkContactPoint> getInitialNetworkContactPoints() { return Collections.unmodifiableList(initialNetworkPeers); } @Override public boolean isRelay() { return localNodeIsRelay; } @Override public long getDelayBeforeStartupConnectAttempts() { // TODO temporary hardcoded default for actual RCE instances; see Mantis #8074 return STARTUP_INITIAL_CONNECT_DELAY_MSEC; } @Override public int getRequestTimeoutMsec() { return configuration.getRequestTimeoutMsec(); } @Override public int getForwardingTimeoutMsec() { return configuration.getForwardingTimeoutMsec(); } @Override public CommunicationIPFilterConfiguration getIPFilterConfiguration() { // not handled in activate() to allow reloading if (initialIPFilterConfigLoaded) { configurationService.reloadConfiguration(); } else { initialIPFilterConfigLoaded = true; } ConfigurationSegment configurationSegment = configurationService.getConfigurationSegment("network/ipFilter"); try { ipFilterConfiguration = configurationSegment.mapToObject(CommunicationIPFilterConfiguration.class); } catch (IOException e) { log.error("Error parsing IP filter configuration; falling back to blocking all IPs!", e); ipFilterConfiguration = new CommunicationIPFilterConfiguration(); ipFilterConfiguration.setEnabled(true); // enable, but do not add IPs -> block all } log.info(StringUtils.format("IP filter enabled: %s, configured number of IPs: %d", ipFilterConfiguration.getEnabled(), ipFilterConfiguration.getAllowedIPs().size())); return ipFilterConfiguration; } /** * OSGi-DS lifecycle method; made public for unit testing. * * @param context OSGi {@link BundleContext} */ public void activate(BundleContext context) { ConfigurationSegment configurationSegment = configurationService.getConfigurationSegment("network"); configuration = new CommunicationConfiguration(configurationSegment); createLocalNodeInformation(); parseNetworkConfiguration(); localNodeIsRelay = configurationService.getIsRelay(); log.info("Local 'isRelay' setting: " + isRelay()); ConfigurationSegment sshConfigurationSegment = configurationService.getConfigurationSegment("sshRemoteAccess"); sshConfiguration = new SshConnectionsConfiguration(sshConfigurationSegment); } /** * OSGi-DS bind method; made public for unit testing. * * @param newService the new {@link ConfigurationService} to set */ public void bindConfigurationService(ConfigurationService newService) { configurationService = newService; } /** * OSGi-DS bind method; made public for unit testing. * * @param newService the new {@link NodeIdentifierService} to set */ public void bindNodeIdentifierService(NodeIdentifierService newService) { this.nodeIdentifierService = newService; } /** * OSGi-DS bind method; made public for unit testing. * * @param newService the new {@link PersistentSettingsService} to set */ public void bindPersistentSettingsService(PersistentSettingsService newService) { persistentSettingsService = newService; } private void createLocalNodeInformation() { String predefinedInstanceIdString = getStoredOrOverriddenInstanceId(); if (predefinedInstanceIdString == null) { localInstanceId = nodeIdentifierService.generateInstanceNodeId(); persistentSettingsService.saveStringValue(PERSISTENT_SETTINGS_KEY_PLATFORM_ID, localInstanceId.getInstanceNodeIdString()); log.info("Generated and stored id " + predefinedInstanceIdString + " for the local node"); } else { try { localInstanceId = nodeIdentifierService.parseInstanceNodeIdString(predefinedInstanceIdString); log.info("Reusing the previously stored id " + predefinedInstanceIdString + " for the local node"); } catch (IdentifierException e) { throw new IllegalStateException("Invalid stored or overridden instance id '" + predefinedInstanceIdString + "'; aborting to avoid running with an inconsistent state"); } } localInstanceSessionId = nodeIdentifierService.generateInstanceNodeSessionId(localInstanceId); String instanceName = configurationService.getInstanceName(); localNodeInformation = new InitialNodeInformationImpl(localInstanceSessionId); localNodeInformation.setDisplayName(instanceName); } private String getStoredOrOverriddenInstanceId() { // check if a node id override is defined String nodeId = System.getProperty(SYSTEM_PROPERTY_OVERRIDE_NODE_ID); if (nodeId != null) { // no need to validate the value; this will be done below anyway log.info("Overriding node id: " + nodeId); } // standard procedure if (nodeId == null) { // check for existing persistent node id nodeId = persistentSettingsService.readStringValue(PERSISTENT_SETTINGS_KEY_PLATFORM_ID); } return nodeId; } private void parseNetworkConfiguration() { // "provided" (server) NCPs List<String> serverContactPointDefs = configuration.getProvidedContactPoints(); log.info("Parsing " + serverContactPointDefs.size() + " server port entries"); for (String contactPointDef : serverContactPointDefs) { NetworkContactPoint ncp; try { ncp = NetworkContactPointUtils.parseStringRepresentation(contactPointDef); log.debug("Adding configured server NCP " + ncp); serverContactPoints.add(ncp); } catch (IllegalArgumentException e) { log.error("Unable to parse contact point definition: " + contactPointDef); } } // "remote" (client) NCPs List<String> remoteContactPointDefs = configuration.getRemoteContactPoints(); log.info("Parsing " + remoteContactPointDefs.size() + " network connection entries"); for (String contactPointDef : remoteContactPointDefs) { NetworkContactPoint ncp; try { ncp = NetworkContactPointUtils.parseStringRepresentation(contactPointDef); log.debug("Adding configured remote NCP " + ncp); initialNetworkPeers.add(ncp); } catch (IllegalArgumentException e) { log.error("Unable to parse contact point definition: " + contactPointDef); } } } @Override public List<InitialSshConnectionConfig> getInitialSSHConnectionConfigs() { return sshConfiguration.getProvidedConnectionConfigs(); } @Override public double[] getLocationCoordinates() { return configurationService.getLocationCoordinates(); } @Override public String getLocationName() { return configurationService.getLocationName(); } @Override public String getInstanceContact() { return configurationService.getInstanceContact(); } @Override public String getInstanceAdditionalInformation() { return configurationService.getInstanceAdditionalInformation(); } }