/**
* Copyright 2014-2017 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.roboconf.agent.internal.misc;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import net.roboconf.core.Constants;
import net.roboconf.core.model.beans.Instance;
import net.roboconf.core.model.helpers.InstanceHelpers;
import net.roboconf.core.utils.ProgramUtils;
import net.roboconf.core.utils.Utils;
/**
* @author Noël - LIG
* @author Pierre-Yves Gibello - Linagora
* @author Amadou Diarra - UGA
*/
public final class AgentUtils {
public static final String INJECTED_CONFIGS_DIR = "roboconf/cfg-injection";
/**
* Private empty constructor.
*/
private AgentUtils() {
// nothing
}
/**
* Checks the syntax of an IP address (basic check, not exhaustive).
* @param ip The IP to check
* @return true if IP looks like an IP address, false otherwise
*/
public static boolean isValidIP( String ip ) {
boolean result = false;
try {
String[] parts;
if( ! Utils.isEmptyOrWhitespaces( ip )
&& (parts = ip.split("\\.")).length == 4 ) {
result = true;
for( String s : parts ) {
int part = Integer.parseInt( s );
if( part < 0 || part > 255 ) {
result = false;
break;
}
}
}
} catch( NumberFormatException e ) {
result = false;
}
return result;
}
/**
* Copies the resources of an instance on the disk.
* @param instance an instance
* @param fileNameToFileContent the files to write down (key = relative file location, value = file's content)
* @throws IOException if the copy encountered a problem
*/
public static void copyInstanceResources( Instance instance, Map<String,byte[]> fileNameToFileContent )
throws IOException {
File dir = InstanceHelpers.findInstanceDirectoryOnAgent( instance );
Utils.createDirectory( dir );
if( fileNameToFileContent != null ) {
for( Map.Entry<String,byte[]> entry : fileNameToFileContent.entrySet()) {
File f = new File( dir, entry.getKey());
Utils.createDirectory( f.getParentFile());
ByteArrayInputStream in = new ByteArrayInputStream( entry.getValue());
Utils.copyStream( in, f );
}
}
}
/**
* Executes a script resource on a given instance.
* @param scriptsDir the scripts directory
* @throws IOException
*/
public static void executeScriptResources( File scriptsDir ) throws IOException {
if( scriptsDir.isDirectory()) {
List<File> scriptFiles = Utils.listAllFiles( scriptsDir );
Logger logger = Logger.getLogger( AgentUtils.class.getName());
for( File script : scriptFiles) {
if( script.getName().contains( Constants.SCOPED_SCRIPT_AT_AGENT_SUFFIX )) {
script.setExecutable( true );
String[] command = { script.getAbsolutePath()};
try {
ProgramUtils.executeCommand( logger, command, script.getParentFile(), null, null, null );
} catch( InterruptedException e ) {
Utils.logException( logger, e );
}
}
}
}
}
/**
* Deletes the resources for a given instance.
* @param instance an instance
* @throws IOException if resources could not be deleted
*/
public static void deleteInstanceResources( Instance instance ) throws IOException {
File dir = InstanceHelpers.findInstanceDirectoryOnAgent( instance );
Utils.deleteFilesRecursively( dir );
}
/**
* Changes the level of the Roboconf logger.
* <p>
* This method assumes the default log configuration for a Roboconf
* distribution has a certain shape. If a user manually changed the log
* configuration (not the level, but the logger name, as an example), then
* this will not work.
* </p>
*/
public static void changeRoboconfLogLevel( String logLevel, String etcDir )
throws IOException {
if( ! Utils.isEmptyOrWhitespaces( etcDir )) {
File f = new File( etcDir, AgentConstants.KARAF_LOG_CONF_FILE );
if( f.exists()) {
Properties props = Utils.readPropertiesFile( f );
props.put( "log4j.logger.net.roboconf", logLevel + ", roboconf" );
Utils.writePropertiesFile( props, f );
}
}
}
/**
* Collect the main log files into a map.
* @param karafData the Karaf's data directory
* @return a non-null map
*/
public static Map<String,byte[]> collectLogs( String karafData ) throws IOException {
Map<String,byte[]> logFiles = new HashMap<>( 2 );
if( ! Utils.isEmptyOrWhitespaces( karafData )) {
String[] names = { "karaf.log", "roboconf.log" };
for( String name : names ) {
File log = new File( karafData, AgentConstants.KARAF_LOGS_DIRECTORY + "/" + name );
if( ! log.exists())
continue;
String content = Utils.readFileContent( log );
logFiles.put( name, content.getBytes( "UTF-8" ));
}
}
return logFiles;
}
/**
* Finds the IP address of the current machine.
* @param networkInterface the network interface to use
* <p>
* If this network interface does not exist, the default one is picked up,
* as returned by <code>InetAddress.getLocalHost().getHostAddress()</code>.
* </p>
*
* @return a non-null IP address (127.0.0.1 in case of error)
*/
public static String findIpAddress( String networkInterface ) {
String ipAddress = null;
Logger logger = Logger.getLogger( AgentUtils.class.getName());
try {
// Try the network interface
NetworkInterface nif;
if( networkInterface != null
&& ! AgentConstants.DEFAULT_NETWORK_INTERFACE.equalsIgnoreCase( networkInterface )
&& (nif = NetworkInterface.getByName( networkInterface )) != null ) {
Enumeration<InetAddress> addrs = nif.getInetAddresses();
while( addrs.hasMoreElements()
&& (ipAddress == null || ipAddress.startsWith( "127.0" ))) {
Object obj = addrs.nextElement();
if( !( obj instanceof Inet4Address ))
continue;
ipAddress = obj.toString();
if( ipAddress.startsWith( "/" ))
ipAddress = ipAddress.substring( 1 );
}
} else if( ! AgentConstants.DEFAULT_NETWORK_INTERFACE.equalsIgnoreCase( networkInterface )) {
logger.severe( "Network interface " + networkInterface + " does not exists. The host's default IP will be picked up." );
}
// Otherwise, use the default address
if( ipAddress == null ) {
logger.fine( "Picking up the host's default IP address." );
ipAddress = InetAddress.getLocalHost().getHostAddress();
}
} catch( Exception e ) {
ipAddress = "127.0.0.1";
logger.warning( "The IP address could not be found. " + e.getMessage());
Utils.logException( logger, e );
}
logger.info( "The agent's address was resolved to " + ipAddress );
return ipAddress;
}
/**
* Generates configuration files from templates.
* @param karafEtc Karaf's etc directory
* @param applicationName the application name
* @param scopedInstancePath the scoped instance path
* @param domain the domain
* @param ipAddress the IP address
*/
public static void injectConfigurations(
String karafEtc,
String applicationName,
String scopedInstancePath,
String domain,
String ipAddress ) {
File injectionDir = new File( karafEtc, INJECTED_CONFIGS_DIR );
if( injectionDir.isDirectory()) {
for( File source : Utils.listAllFiles( injectionDir, ".cfg.tpl" )) {
try {
File target = new File( karafEtc, source.getName().replaceFirst( "\\.tpl$", "" ));
// Do not overwrite the agent's configuration file (infinite configuration loop)
if( UserDataUtils.CONF_FILE_AGENT.equalsIgnoreCase( target.getName()))
continue;
String content = Utils.readFileContent( source );
content = content.replace( "<domain>", domain );
content = content.replace( "<application-name>", applicationName );
content = content.replace( "<scoped-instance-path>", scopedInstancePath );
content = content.replace( "<ip-address>", ipAddress );
Utils.writeStringInto( content, target );
} catch( IOException e ) {
Logger logger = Logger.getLogger( AgentUtils.class.getName());
logger.severe( "A configuration file could not be injected from " + source.getName());
Utils.logException( logger, e );
}
}
}
}
}