/** * Stops an instance (prerequisite: DEPLOYED_STARTED). * @param instance the instance * @param plugin the associated plug-in * @throws IOException if something went wrong */ void stop( Instance instance, PluginInterface plugin ) throws IOException { String instancePath = InstanceHelpers.computeInstancePath( instance ); if( instance.getStatus() != InstanceStatus.DEPLOYED_STARTED ) this.logger.fine( instancePath + " cannot be stopped. Prerequisite status: DEPLOYED_STARTED (but was " + instance.getStatus() + ")." ); else stopInstance( instance, plugin, false ); }
/** * Acknowledges a heart beat. * @param scopedInstance a root instance */ public void acknowledgeHeartBeat( Instance scopedInstance ) { String count = scopedInstance.data.get( MISSED_HEARTBEATS ); if( count != null && Integer.parseInt( count ) > THRESHOLD ) this.logger.info( "Agent " + InstanceHelpers.computeInstancePath( scopedInstance ) + " is alive and reachable again." ); // Store the moment the first ACK (without interruption) was received. // If we were deploying, store it. // If we were in problem, store it. // If we were already deployed and started, do NOT override it. if( scopedInstance.getStatus() != InstanceStatus.DEPLOYED_STARTED || ! scopedInstance.data.containsKey( Instance.RUNNING_FROM )) scopedInstance.data.put( Instance.RUNNING_FROM, String.valueOf( new Date().getTime())); scopedInstance.setStatus( InstanceStatus.DEPLOYED_STARTED ); scopedInstance.data.remove( MISSED_HEARTBEATS ); }
/** * Constructor. * @param applicationName the application name * @param instance the changed instance */ public MsgNotifInstanceChanged( String applicationName, Instance instance ) { super(); this.instancePath = InstanceHelpers.computeInstancePath( instance ); this.newImports = instance.getImports(); this.newStatus = instance.getStatus(); this.applicationName = applicationName; }
/** * Constructor. * @param applicationName the application name * @param instance the changed instance */ public MsgNotifInstanceChanged( String applicationName, Instance instance ) { super(); this.instancePath = InstanceHelpers.computeInstancePath( instance ); this.newImports = instance.getImports(); this.newStatus = instance.getStatus(); this.applicationName = applicationName; }
/** * Republishes all the variables managed by this agent. * @param message the initial request * @throws IOException if an error occurred with the messaging */ void processMsgResynchronize( MsgCmdResynchronize message ) throws IOException { if( this.scopedInstance != null ) { for( Instance i : InstanceHelpers.buildHierarchicalList( this.scopedInstance )) { if( i.getStatus() == InstanceStatus.DEPLOYED_STARTED ) this.messagingClient.publishExports( i ); } } }
@Override public int pingAgent( ManagedApplication app, Instance scopedInstance, String message ) { int result; MsgEcho ping = new MsgEcho( "PING:" + message ); try { if( scopedInstance.getStatus() != InstanceStatus.NOT_DEPLOYED ) { this.messagingMngr.sendMessageDirectly( app, scopedInstance, ping ); this.logger.fine( "Sent PING request message=" + message + " to application=" + app + ", agent=" + scopedInstance ); result = 0; } else { this.logger.fine( "No PING request was sent to application=" + app + ", agent=" + scopedInstance + ". The agent was not started." ); result = 1; } } catch( IOException e ) { this.logger.fine( "No PING request was sent to application=" + app + ", agent=" + scopedInstance + ". An error occurred with the messaging." ); Utils.logException( this.logger, e ); result = 2; } return result; }
@Override public void dissociateTargetFrom( AbstractApplication app, String instancePathOrComponentName ) throws IOException, UnauthorizedActionException { if( instancePathOrComponentName != null && ! instancePathOrComponentName.startsWith( "@" )) { Instance instance = InstanceHelpers.findInstanceByPath( app, instancePathOrComponentName ); if( instance != null ) { if( instance.getStatus() != InstanceStatus.NOT_DEPLOYED ) throw new UnauthorizedActionException( "Operation not allowed: " + app + " :: " + instancePathOrComponentName + " should be not deployed." ); if( ! InstanceHelpers.isTarget( instance )) throw new IllegalArgumentException( "Only scoped instances can be associated with targets. Path in error: " + instancePathOrComponentName ); } } saveAssociation( app, null, instancePathOrComponentName, false ); }
/** * Publishes its exports when required. * @param msg the message process * @throws IOException if an error occurred with the messaging */ void processMsgRequestImport( MsgCmdRequestImport msg ) throws IOException { for( Instance instance : InstanceHelpers.buildHierarchicalList( this.scopedInstance )) { if( instance.getStatus() == InstanceStatus.DEPLOYED_STARTED ) this.messagingClient.publishExports( instance, msg.getComponentOrFacetName()); } }
@Override public void associateTargetWith( String targetId, AbstractApplication app, String instancePathOrComponentName ) throws IOException, UnauthorizedActionException { boolean valid = false; if( instancePathOrComponentName == null ) { valid = true; } else if( instancePathOrComponentName.startsWith( "@" )) { Component comp = ComponentHelpers.findComponent( app, instancePathOrComponentName.substring( 1 )); valid = comp != null; } else { Instance instance = InstanceHelpers.findInstanceByPath( app, instancePathOrComponentName ); valid = instance != null; if( instance != null ) { if( instance.getStatus() != InstanceStatus.NOT_DEPLOYED ) throw new UnauthorizedActionException( "Operation not allowed: " + app + " :: " + instancePathOrComponentName + " should be not deployed." ); if( ! InstanceHelpers.isTarget( instance )) throw new IllegalArgumentException( "Only scoped instances can be associated with targets. Path in error: " + instancePathOrComponentName ); } } if( valid ) saveAssociation( app, targetId, instancePathOrComponentName, true ); }
@Override public void resynchronizeAgents( ManagedApplication ma ) throws IOException { this.messagingMngr.checkMessagingConfiguration(); this.logger.fine( "Resynchronizing agents in " + ma.getName() + "..." ); for( Instance rootInstance : ma.getApplication().getRootInstances()) { if( rootInstance.getStatus() == InstanceStatus.DEPLOYED_STARTED ) this.messagingMngr.sendMessageDirectly( ma, rootInstance, new MsgCmdResynchronize()); } this.logger.fine( "Requests were sent to resynchronize agents in " + ma.getName() + "." ); }
/** * Starts children instances when they are waiting for their ancestors to start. * <p> * To invoke every time imports change. * </p> * @throws IOException if something went wrong * @throws PluginException if something went wrong */ private void startChildrenInstancesWaitingForAncestors() throws IOException, PluginException { List<Instance> childrenInstances = InstanceHelpers.buildHierarchicalList( this.scopedInstance ); childrenInstances.remove( this.scopedInstance ); for( Instance childInstance : childrenInstances ) { if( childInstance.getStatus() != InstanceStatus.WAITING_FOR_ANCESTOR ) continue; if( childInstance.getParent().getStatus() != InstanceStatus.DEPLOYED_STARTED ) continue; PluginInterface plugin = this.agent.findPlugin( childInstance ); if( plugin == null ) this.logger.severe( "No plug-in was found for " + InstanceHelpers.computeInstancePath( childInstance ) + "." ); else AbstractLifeCycleManager .build( childInstance, this.agent.getApplicationName(), this.messagingClient) .changeInstanceState( childInstance, plugin, InstanceStatus.DEPLOYED_STARTED, null ); } } }
@Override public void sendStoredMessages( ManagedApplication ma, Instance instance ) { if( messagingIsReady()) { // If the VM is online, process awaiting messages to prevent waiting. // This can work concurrently with the messages timer. Instance scopedInstance = InstanceHelpers.findScopedInstance( instance ); if( scopedInstance.getStatus() == InstanceStatus.DEPLOYED_STARTED ) { List<Message> messages = ma.removeAwaitingMessages( instance ); if( messages.isEmpty()) return; String path = InstanceHelpers.computeInstancePath( scopedInstance ); this.logger.fine( "Forcing the sending of " + messages.size() + " awaiting message(s) for " + path + "." ); for( Message msg : messages ) { try { sendMessageDirectly( ma, scopedInstance, msg ); } catch( IOException e ) { // If the message could not be send, plan a retry. // This preserves message ordering (FIFO). ma.storeAwaitingMessage( scopedInstance, msg ); this.logger.severe( "Error while sending a stored message. A retry is planned. " + e.getMessage()); Utils.logException( this.logger, e ); } } } } }
if( childInstance.getStatus() == InstanceStatus.WAITING_FOR_ANCESTOR ) childInstance.setStatus( InstanceStatus.DEPLOYED_STOPPED );
@Override public void execute() throws CommandException { Instance instance = resolveInstance( this.instr, this.instr.getInstancePath(), false ); Instance scopedInstance = InstanceHelpers.findScopedInstance( instance ); if( scopedInstance.getStatus() != InstanceStatus.NOT_DEPLOYED ) throw new CommandException( "Only instances that are not yet managed by an agent can be renamed." ); instance.setName( this.instr.getNewInstanceName()); } }
@Override public void changeInstanceState( Instance instance, PluginInterface plugin, InstanceStatus newStatus, Map<String,byte[]> fileNameToFileContent ) throws IOException, PluginException { // We can undeploy if( newStatus == InstanceStatus.NOT_DEPLOYED ) undeploy( instance, plugin ); // Stop is only a status change, no script or notification run else if( newStatus == InstanceStatus.DEPLOYED_STOPPED ) { instance.setStatus( InstanceStatus.DEPLOYED_STOPPED ); this.messagingClient.sendMessageToTheDm( new MsgNotifInstanceChanged( this.appName, instance )); List<Instance> childrenInstances = InstanceHelpers.buildHierarchicalList( instance ); childrenInstances.remove( instance ); for( Instance childInstance : childrenInstances ) { // Unresolved can only have "deployed stopped", "not deployed" and "waiting for ancestor" child status. if( childInstance.getStatus() == InstanceStatus.WAITING_FOR_ANCESTOR ) { childInstance.setStatus( InstanceStatus.DEPLOYED_STOPPED ); this.messagingClient.sendMessageToTheDm( new MsgNotifInstanceChanged( this.appName, childInstance )); } } } } }
switch( instance.getStatus()) { case DEPLOYED_STARTED: result = new DeployedStarted( appName, messagingClient );
@Test public void testDuplicateInstance_singleInstance() { Instance original = new Instance( "inst" ).channel( "chan" ).component( new Component( "comp" )); original.overriddenExports.put( "test", "test" ); original.overriddenExports.put( "A.port", "8012" ); original.data.put( "some", "data" ); original.getImports().put( "facet-name", new ArrayList<Import> ()); original.setStatus( InstanceStatus.DEPLOYED_STARTED ); Instance copy = InstanceHelpers.replicateInstance( original ); Assert.assertEquals( original.getName(), copy.getName()); Assert.assertEquals( original.channels, copy.channels ); Assert.assertEquals( original.overriddenExports.size(), copy.overriddenExports.size()); Assert.assertEquals( "test", copy.overriddenExports.get( "test" )); Assert.assertEquals( "8012", copy.overriddenExports.get( "A.port" )); Assert.assertEquals( 0, copy.getImports().size()); Assert.assertEquals( original.getComponent(), copy.getComponent()); Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, copy.getStatus()); }
Assert.assertEquals( InstanceStatus.NOT_DEPLOYED, instance.getStatus());
@Test public void testRuntimeData() throws Exception { // The graph Graphs graphs = new Graphs(); Component vmComponent = new Component( "vm" ).installerName( Constants.TARGET_INSTALLER ); graphs.getRootComponents().add( vmComponent ); // The file to read File f = TestUtils.findTestFile( "/configurations/valid/single-runtime-instance.instances" ); FromInstanceDefinition fromDef = new FromInstanceDefinition( f.getParentFile()); Collection<Instance> rootInstances = fromDef.buildInstances( graphs, f ); Assert.assertEquals( 0, fromDef.getErrors().size()); // The assertions Assert.assertEquals( 1, rootInstances.size()); Instance instance = rootInstances.iterator().next(); Assert.assertEquals( "vm 1", instance.getName()); Assert.assertEquals( vmComponent, instance.getComponent()); Assert.assertEquals( InstanceStatus.DEPLOYED_STARTED, instance.getStatus()); Assert.assertEquals( 3, instance.data.size()); Assert.assertEquals( "127.0.0.1", instance.data.get( "ip" )); Assert.assertEquals( "mach-ID", instance.data.get( "machine-id" )); Assert.assertEquals( "something different", instance.data.get( "whatever" )); }
@Test public void testChain() { Instance inst = new Instance().name( "ins" ).status( InstanceStatus.DEPLOYING ).component( null ).parent( null ); Assert.assertEquals( 0, inst.channels.size()); Assert.assertEquals( "ins", inst.getName()); Assert.assertEquals( InstanceStatus.DEPLOYING, inst.getStatus()); Assert.assertNull( inst.getComponent()); Assert.assertNull( inst.getParent()); Assert.assertEquals( 1, inst.channel( "woo" ).channels.size()); Assert.assertEquals( 2, inst.channel( "yeah" ).channels.size()); Assert.assertEquals( 2, inst.channel( "woo" ).channels.size()); }