/**
* Copyright 2015-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.karaf.commands.dm.diagnostics;
import java.io.PrintStream;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import net.roboconf.core.model.beans.Application;
import net.roboconf.core.model.beans.ApplicationTemplate;
import net.roboconf.core.model.beans.Instance;
import net.roboconf.core.model.beans.Instance.InstanceStatus;
import net.roboconf.core.model.helpers.InstanceHelpers;
import net.roboconf.core.model.runtime.EventType;
import net.roboconf.dm.management.Manager;
import net.roboconf.dm.management.events.IDmListener;
import net.roboconf.karaf.commands.dm.KarafDmCommandsUtils;
import net.roboconf.karaf.commands.dm.KarafDmCommandsUtils.RbcfInfo;
import net.roboconf.karaf.commands.dm.completers.ApplicationCompleter;
import net.roboconf.karaf.commands.dm.completers.ScopedInstanceCompleter;
/**
* @author Vincent Zurczak - Linagora
*/
@Command( scope = "roboconf", name = "diagnostic-messaging", description="Verifies messaging works" )
@Service
public class DiagnosticMessagingCommand implements Action {
@Argument( index = 0, name = "application", description = "The application's name", required = true, multiValued = false )
@Completion( ApplicationCompleter.class )
String applicationName;
@Argument( index = 1, name = "scoped instance's path", description = "The scoped instance's path", required = false, multiValued = false )
@Completion( ScopedInstanceCompleter.class )
String scopedInstancePath;
@Reference
Manager manager;
// Other fields
final Logger logger = Logger.getLogger( getClass().getName());
final Map<String,String> uuidToTarget = new ConcurrentHashMap<> ();
final Map<String,Boolean> uuidToFound = new ConcurrentHashMap<> ();
PrintStream out = System.out;
int waitingDelay = 5;
@Override
public Object execute() throws Exception {
// Check...
RbcfInfo info = KarafDmCommandsUtils.findInstances( this.manager, this.applicationName, this.scopedInstancePath, this.out );
// Execute
if( ! info.getScopedInstances().isEmpty()) {
DiagnosticListener listener = new DiagnosticListener( this.uuidToFound );
try {
this.manager.listenerAppears( listener );
// DM
this.out.println( "Pinging the DM..." );
String uuid = UUID.randomUUID().toString();
this.uuidToTarget.put( uuid, "The DM" );
this.manager.debugMngr().pingMessageQueue( uuid );
// Agents
for( Instance inst : info.getScopedInstances()) {
String path = InstanceHelpers.computeInstancePath( inst );
if( inst.getStatus() != InstanceStatus.DEPLOYED_STARTED ) {
this.out.println( "Skipping agent " + path + " as it is not deployed and started." );
continue;
}
this.out.println( "Pinging agent " + path );
uuid = UUID.randomUUID().toString();
this.uuidToTarget.put( uuid, "Agent " + path );
this.manager.debugMngr().pingAgent( info.getManagedApplication(), inst, uuid );
}
// Wait few seconds maximum
this.out.println( "" );
this.out.println( "Waiting few seconds to get PING results..." );
this.out.println( "" );
Thread.sleep( this.waitingDelay * 1000 );
} finally {
this.manager.listenerDisappears( listener );
listener = null;
this.out.println( "" );
this.out.print( "The " + this.waitingDelay + " second" );
if( this.waitingDelay > 1 )
this.out.print( "s" );
this.out.print( " delay elapsed." );
this.out.println( "" );
// Show successes first
for( Map.Entry<String,String> entry : this.uuidToTarget.entrySet()) {
Boolean b = this.uuidToFound.get( entry.getKey());
if( b != null && b )
this.out.println( "[ SUCCESS ] " + entry.getValue() + " responded to the ping." );
}
// And failures then
this.out.println( "" );
for( Map.Entry<String,String> entry : this.uuidToTarget.entrySet()) {
Boolean b = this.uuidToFound.get( entry.getKey());
if( b == null || ! b )
this.out.println( "[ FAILURE ] " + entry.getValue() + " did not respond to the ping." );
}
}
}
return null;
}
/**
* @author Vincent Zurczak - Linagora
*/
static class DiagnosticListener implements IDmListener {
Map<String,Boolean> uuidToFound;
/**
* Constructor.
* @param uuidToFound
*/
public DiagnosticListener( Map<String,Boolean> uuidToFound ) {
this.uuidToFound = uuidToFound;
}
@Override
public String getId() {
return "karaf-command-to-diagnostic-messaging :: " + UUID.randomUUID().toString();
}
@Override
public void enableNotifications() {
// nothing
}
@Override
public void disableNotifications() {
// nothing
}
@Override
public void application( Application application, EventType eventType ) {
// nothing
}
@Override
public void applicationTemplate( ApplicationTemplate tpl, EventType eventType ) {
// nothing
}
@Override
public void instance( Instance instance, Application application, EventType eventType ) {
// nothing
}
@Override
public void raw( String message, Object... data ) {
String uuid = message.replaceFirst( "^PONG:", "" );
this.uuidToFound.put( uuid, Boolean.TRUE );
}
}
}