3 import java.io.BufferedReader;
5 import java.io.IOException;
6 import java.io.InputStreamReader;
7 import java.rmi.Naming;
8 import java.rmi.RemoteException;
9 import java.rmi.registry.LocateRegistry;
10 import java.rmi.registry.Registry;
11 import java.rmi.server.UnicastRemoteObject;
12 import java.util.ArrayList;
13 import java.util.Iterator;
16 public class Server extends UnicastRemoteObject implements ServicesServer
18 private class DiscCount
22 DiscCount() { nb = 0 ; }
24 protected void inc() { nb++ ; }
26 protected void dec() {
33 protected int getNb() { return nb ; }
37 private class ConnectedClient
39 private ServicesClient stub ;
41 private Status state ;
44 private ComputingClient cl ;
46 ConnectedClient( ServicesClient _stub )
50 state = new Status() ;
51 state.setStatus( "connected" ) ;
53 ip = stub.getIPHost() ;
54 name = stub.getName() ;
55 } catch (RemoteException e) {
61 protected ServicesClient getStub() { return stub ; }
63 protected void setStub( ServicesClient _stub ) { stub = _stub ; }
65 protected int getTimeout() { return timeout ; }
67 protected void incTimeout() { timeout++ ; }
69 protected void resetTimeout() { timeout = 0 ; }
71 protected String getStatus() { return state.getStatus() ; }
73 protected void setStatus( String _state ) { state.setStatus( _state ) ; }
75 protected String getIP() { return ip ; }
77 protected String getName() { return name ; } ;
79 protected void setComputingClient( ComputingClient _cl ) { cl = _cl ; }
81 protected ComputingClient getComputingClient() { return cl ; }
85 private class ComputingClient
87 private ConnectedClient client ;
88 private boolean save_status ;
89 private ArrayList<ServicesClient> save_neighbor ;
90 private String lastSaveName ;
92 ComputingClient( ConnectedClient cl )
96 save_neighbor = new ArrayList<ServicesClient>() ;
97 lastSaveName = "none" ;
100 protected ConnectedClient getClient() { return client ; }
102 protected boolean getSaveStatus(){ return save_status ; }
104 protected void setSaveStatus( boolean _status ) { save_status = _status ; }
106 protected void setSaveNeighbor( ServicesClient _sn )
110 if( save_neighbor.size() == 0 )
112 save_neighbor.add( _sn ) ;
114 save_neighbor.set( 0, _sn ) ;
117 // System.out.println( "My save neighbor is " + _sn ) ;
120 client.getStub().setSavingNeighbor( _sn ) ;
121 } catch( RemoteException e ) {
122 System.err.println( "Error while setting save neighbor on " +
123 client.getName() + "(" + client.getIP() + ")!" ) ;
124 e.printStackTrace() ;
129 protected ServicesClient getSaveNeighbor()
131 if( save_neighbor.isEmpty() )
135 return save_neighbor.get( 0 ) ;
139 public void setLastSave( String _saveName )
141 lastSaveName = _saveName ;
144 public String getLastSave() { return lastSaveName ; }
149 private class IPAssociation
151 private String vmIP ;
152 private String hostIP ;
160 protected void setVmIP( String _vmIP )
165 protected void setHostIP( String _hostIP )
170 protected String getVmIP()
175 protected String getHostIP()
183 private static final long serialVersionUID = 1L ;
185 private ArrayList<ConnectedClient> clients ;
186 private ArrayList<ComputingClient> computingClients ;
187 private int max_timeout ;
188 private ConnectedMonitor monitor ;
189 private DiscCount counter ;
190 private ArrayList<IPAssociation> vmIPs ;
191 private String working_directory ;
194 protected Server() throws RemoteException
202 public Integer register( ServicesClient _stub )
208 ip = _stub.getIPHost() ;
209 } catch (RemoteException e) {
210 e.printStackTrace() ;
214 boolean exists = false ;
217 for( i = 0 ; i < clients.size() ; i++ )
219 if( ip.equals( clients.get( i ).getIP() ) )
222 System.out.println( "Client already connected!" ) ;
229 System.out.println( "The client stub will be replaced." ) ;
230 clients.get( i ).setStub( _stub ) ;
231 System.out.println( "(reconnection of " + clients.get( i ).getName() + ")" ) ;
234 System.out.println( "New connection!" ) ;
235 clients.add( new ConnectedClient( _stub ) ) ;
236 System.out.println( "(connection of " + clients.get( clients.size() - 1 ).getName() + ")" ) ;
239 if( clients.size() == 0 )
241 System.out.println( "There is no client connected." ) ;
242 } else if( clients.size() == 1 ) {
243 System.out.println( "There is one client connected." ) ;
245 System.out.println( "There are " + clients.size() + " clients connected." ) ;
256 private void generateVmIP( String _ip )
258 if( _ip != null && ! _ip.equals( "" ) )
260 for( int i = 0 ; i < vmIPs.size() ; i++ )
262 if( vmIPs.get( i ).getHostIP() == null )
264 vmIPs.get( i ).setHostIP( _ip ) ;
274 public void ping( String _ip )
278 for( int i = 0 ; i < clients.size() ; i++ )
280 if( _ip.equals( clients.get( i ).getIP() ) )
282 clients.get( i ).resetTimeout() ;
291 public void changeStatus( String _ip, String _status )
293 if( _ip != null && _status != null )
295 for( int i = 0 ; i < clients.size() ; i++ )
297 if( _ip.equals( clients.get( i ).getIP() ) )
299 clients.get( i ).setStatus( _status ) ;
300 System.out.println( "Client " + clients.get( i ).getName() + " changed its status to: " + _status ) ;
308 public void init( int _port )
313 clients = new ArrayList<Server.ConnectedClient>() ;
314 computingClients = new ArrayList<Server.ComputingClient>() ;
317 working_directory = "/localhome/vmware" ;
321 vmIPs = new ArrayList<IPAssociation>() ;
322 // TODO initialisation of VM IPs
323 for( int i = 2 ; i < 101 ; i++ )
325 vmIPs.add( new IPAssociation() ) ;
326 vmIPs.get( vmIPs.size() - 1 ).setVmIP( "10.11.10." + i ) ;
329 clients = new ArrayList<Server.ConnectedClient>() ;
331 counter = new DiscCount() ;
333 monitor = new ConnectedMonitor() ;
340 if( monitor != null ) { monitor.stopMonitor() ; }
342 for( int i = 0 ; i < clients.size() ; i++ )
345 clients.get( i ).getStub().stop() ;
346 } catch (RemoteException e) {
357 private void exportObject()
359 ServicesServer ref = null ;
360 Registry reg = null ;
366 reg = LocateRegistry.getRegistry( port ) ;
368 String tab[] = reg.list() ;
370 System.out.println( "There is an existing RMI Registry on port " +
371 port + " with " + tab.length + " entries!" ) ;
372 for( int i = 0 ; i < tab.length ; i++ )
375 if( UnicastRemoteObject.unexportObject( Naming.lookup(tab[i]), true ) )
377 System.out.println( "Register successfuly deleted!" ) ;
379 System.err.println( "Register undeleted !!!" ) ;
381 } catch( Exception e ) {
382 e.printStackTrace() ;
386 } catch( RemoteException e ) {
390 if ( System.getSecurityManager() == null )
392 System.setSecurityManager( new SecurityManager() ) ;
395 LocateRegistry.createRegistry( port ) ;
396 LocateRegistry.getRegistry( port ).rebind( "Server", this ) ;
397 ref = (ServicesServer) Naming.lookup( "rmi://"
398 + LocalHost.Instance().getIP() + ":" + port
400 } catch ( Exception e ) {
401 System.err.println( "Error in Server.exportObject() when creating local services:" + e ) ;
402 System.err.println( "Exit from Server.exportObject" ) ;
406 LocalHost.Instance().setServerStub( ref ) ;
408 System.out.println( "Server launched on IP " + LocalHost.Instance().getIP() +
409 " on port " + port + "." ) ;
412 /** Fault manager thread **/
413 private class FaultManager extends Thread
417 FaultManager( ConnectedClient _cl )
425 if( cl != null && cl.getStatus().equalsIgnoreCase( "running" ) ||
426 cl.getStatus().equalsIgnoreCase( "saving" ) )
428 ComputingClient cc = cl.getComputingClient() ;
429 // ServicesClient dead = cc.getClient().getStub() ;
430 String ipDead = cc.getClient().getIP() ;
434 for( int i = 0 ; i < clients.size() ; i++ )
436 if( clients.get( i ).getStatus().equalsIgnoreCase( "connected" ) )
440 // res = clients.get( i ).getStub().startVM() ;
441 // } catch( RemoteException e ) {
442 // e.printStackTrace();
447 //clients.get(i).setStatus( "running" ) ;
449 int pos = computingClients.indexOf( cc ) ;
452 System.err.println( "Dead client not found in the computing clients list!" ) ;
454 System.out.println( "Trying to replace " + cc.getClient().getName() + " with " +
455 clients.get(i).getName() + " ... " ) ;
457 String save_name = computingClients.get( pos ).getLastSave() ;
459 ComputingClient ccl = new ComputingClient( clients.get(i) ) ;
460 clients.get( i ).setComputingClient( ccl ) ;
461 ServicesClient sn = computingClients.get( pos ).getSaveNeighbor() ;
462 ccl.setSaveNeighbor( sn ) ;
463 computingClients.set( pos, ccl ) ;
468 res = computingClients.get( pos ).getClient().getStub().
469 retrieveSave( save_name ) ;
470 } catch( RemoteException e ) {
471 System.err.println( "Unable to indicate to client to retrieve last save!" ) ;
472 e.printStackTrace() ;
479 // replace dead client in vmIPs
480 for( int j = 0 ; j < vmIPs.size() ; j++ )
482 if( vmIPs.get( j ).getHostIP().equalsIgnoreCase( ipDead ) )
484 String vmIP = vmIPs.get( j ).getVmIP() ;
485 vmIPs.get( j ).setHostIP( computingClients.get( pos ).getClient().getIP() ) ;
488 computingClients.get( pos ).getClient().getStub().setIPVM( vmIP ) ;
489 } catch( RemoteException e ) {
490 System.err.println( "Unable to set the new VM IP on the replacing client!" ) ;
491 e.printStackTrace() ;
497 System.out.println( "Successful redeployment of the VM." ) ;
499 System.err.println( "Unable to deploy the save on the new computing client!" ) ;
503 // System.err.println( "Problem while launching the VM on "
504 // + clients.get(i).getName() + "!" ) ;
509 for( int k = 0 ; k < computingClients.size() ; k++ )
512 computingClients.get( k ).getClient().getStub().
513 replaceSavingNeighbor( ipDead, clients.get( i ).getStub() ) ;
514 } catch( RemoteException e ) {
515 System.err.println( "Unable to inform " + computingClients.get( k ).getClient().getName() +
516 " of the replacement of a save neighbor!" ) ;
517 e.printStackTrace() ;
521 System.out.println( "Dead client successfully replaced." ) ;
525 System.err.println( "Dead client not replaced!!" ) ;
532 synchronized( counter ) {
534 counter.notifyAll() ;}
535 } catch( Exception e ) {}
540 /** Monitoring thread **/
541 private class ConnectedMonitor extends Thread
550 protected void stopMonitor() { run = false ; }
560 Iterator<ConnectedClient> it = clients.iterator() ;
561 int nb_disconnections = 0 ;
562 int nb_disconnections_computing = 0 ;
564 while( it.hasNext() )
566 ConnectedClient cl = it.next() ;
569 if( cl.getTimeout() > max_timeout )
571 System.out.println( "Disconnection of " + cl.getName() ) ;
572 if( cl.getStatus().equalsIgnoreCase( "running" ) || cl.getStatus().equalsIgnoreCase( "saving" ) )
574 System.out.println( "A VM was running on it!!" ) ;
575 System.out.println( "I will redeploy a save and restart all VM ..." ) ;
577 // for( int i = 0 ; i < computingClients.size() ; i++ )
579 // if( computingClients.get( i ).getClient().getIP().equals( cl.getIP() ) )
581 // computingClients.remove( i ) ;
585 synchronized( counter ){
589 new Server.FaultManager( cl ).start() ;
590 nb_disconnections_computing++ ;
592 System.out.println( "There was no VM running on it." ) ;
593 System.out.println( "Maybe it will come back later :)" ) ;
597 nb_disconnections++ ;
604 if( clients.size() == 0 )
606 System.out.println( "There is no client connected." ) ;
607 } else if( clients.size() == 1 ) {
608 System.out.println( "There is one client connected." ) ;
610 System.out.println( "There are " + clients.size() + " clients connected." ) ;
615 if( nb_disconnections_computing > 0 )
617 System.out.println( "Sending emergency stop signal to all computing nodes ... " ) ;
619 for( int i = 0 ; i < clients.size() ; i++ )
621 if( clients.get( i ).getStatus().equalsIgnoreCase( "running" )
622 || clients.get( i ).getStatus().equalsIgnoreCase( "saving" ) )
625 clients.get( i ).getStub().emergencyStop() ;
626 } catch( RemoteException e ) {
627 System.err.println( "Unable to invoke emergency stop signal on " + clients.get( i ).getName() ) ;
628 e.printStackTrace() ;
633 System.out.println( "I will redeploy save and restart VMs ... " ) ;
635 synchronized( counter )
637 if( counter.getNb() > 0 )
639 System.out.println( "... waiting all redeployments done ..." ) ;
642 while( counter.getNb() != 0 )
646 } catch( InterruptedException e ) {
647 e.printStackTrace() ;
652 for( int i = 0 ; i < computingClients.size() ; i++ )
654 final ServicesClient sc = computingClients.get( i ).getClient().getStub() ;
656 new Thread( new Runnable() {
662 sc.restartVMAfterCrash() ;
663 } catch( RemoteException e ) {
664 e.printStackTrace() ;
673 Thread.sleep( 2000 ) ;
674 } catch( InterruptedException e ) {
675 e.printStackTrace() ;
682 public Integer saveOk( String _ip, String _saveName )
685 for( i = 0 ; i < computingClients.size() ; i ++ )
687 if( computingClients.get( i ).getClient().getIP().equalsIgnoreCase( _ip ) )
689 computingClients.get( i ).setLastSave( _saveName ) ;
690 computingClients.get( i ).setSaveStatus( true ) ;
696 boolean all_ok = true ;
699 while( all_ok && i < computingClients.size() )
701 all_ok = all_ok & computingClients.get( i ).getSaveStatus() ;
707 for( i = 0 ; i < computingClients.size() ; i++ )
710 computingClients.get( i ).getClient().getStub().saveOk() ;
711 } catch (RemoteException e) {
714 computingClients.get( i ).setSaveStatus( false ) ;
722 public Integer changeSaveName( String _ip, String _saveName )
724 if( _ip != null && _ip.length() > 0 && _saveName != null && _saveName.length() > 0 )
726 for( int i = 0 ; i < computingClients.size() ; i ++ )
728 if( computingClients.get( i ).getClient().getIP().equalsIgnoreCase( _ip ) )
730 computingClients.get( i ).setLastSave( _saveName ) ;
731 System.out.println( "Save name successfully change for " + _ip ) ;
741 public ArrayList<ServicesClient> startApplication( int _nb )
743 int nb = clients.size() - computingClients.size() ;
747 ArrayList<ServicesClient> ac = new ArrayList<ServicesClient>() ;
748 ArrayList<ComputingClient> tmp = new ArrayList<Server.ComputingClient>() ;
752 while( i < clients.size() && ac.size() < _nb )
754 if( clients.get(i).getStatus().equalsIgnoreCase( "connected" ) )
758 res = clients.get( i ).getStub().startVM( 0 ) ;
759 } catch( RemoteException e ) {
765 ac.add( clients.get( i ).getStub() ) ;
766 clients.get( i ).setStatus( "running" ) ;
767 ComputingClient cl = new ComputingClient( clients.get( i ) ) ;
768 clients.get( i ).setComputingClient( cl ) ;
769 computingClients.add( cl ) ;
772 System.err.println( "Problem while launching the VM on "
773 + clients.get(i).getName() + "!" ) ;
780 if( ac.size() == _nb )
783 /* Choosing save neighbors */
784 for( i = 0 ; i < tmp.size() ; i++ )
786 if( i == tmp.size() - 1 )
788 index = computingClients.indexOf( tmp.get( i ) ) ;
789 index2 = computingClients.indexOf( tmp.get( 0 ) ) ;
791 if( index == -1 || index2 == -1 )
793 System.err.println( "Problem in ComputingClients list!" ) ;
795 computingClients.get( index ).setSaveNeighbor( computingClients.get( index2 ).getClient().getStub() ) ;
798 index = computingClients.indexOf( tmp.get( i ) ) ;
799 index2 = computingClients.indexOf( tmp.get( i + 1 ) ) ;
801 if( index == -1 || index2 == -1 )
803 System.err.println( "Problem in ComputingClients list!" ) ;
805 computingClients.get( index ).setSaveNeighbor( computingClients.get( index2 ).getClient().getStub() ) ;
824 public void endApplication()
826 Iterator<ComputingClient> it = computingClients.iterator() ;
828 while( it.hasNext() )
830 ComputingClient cl = it.next() ;
833 cl.getClient().getStub().stopVM() ;
834 } catch (RemoteException e) {
838 cl.getClient().setStatus( "connected" ) ;
839 cl.getClient().setComputingClient( null ) ;
849 public String getAssociatedIP( String _ip )
853 for( int i = 0 ; i < vmIPs.size() ; i++ )
855 if( vmIPs.get( i ).getHostIP().equalsIgnoreCase( _ip ) )
857 ret = vmIPs.get( i ).getVmIP() ;
866 public Integer deployVM( String _name, String _archive, String _directory )
871 if( _name != null && _name.length() > 0 && _archive != null && _name.length() > 0
872 && _directory != null && _directory.length() > 0 )
874 System.out.println( "Deploying the VM " + _name + " (" + _archive + ") ... " ) ;
876 File file = new File( working_directory + "/" + _archive ) ;
877 if( ! file.exists() )
879 System.err.println( "There is no archive named " + _archive + " in my working directory!" ) ;
882 } else if( file.isDirectory() ) {
883 System.err.println( _archive + " is a directory!" ) ;
890 // TODO do a better deployment !!
896 for( int i = 0 ; i < clients.size() ; i++ )
901 ret = clients.get( i ).getStub().deployVM( _name, _archive, _directory ) ;
902 } catch( RemoteException e ) {
903 System.err.println( "Unable to deploy the VM on " + clients.get( i ).getName() + "!" ) ;
904 e.printStackTrace() ;
907 // The client does not have the archive, we have to send it.
910 System.out.print( "Sending VM archive to " + clients.get( i ).getName() + " ... " ) ;
917 wd = clients.get( i ).getStub().getWorkingDirectory() ;
918 snIP = clients.get( i ).getStub().getIPHost() ;
919 } catch (RemoteException e2) {
920 System.err.println( "Unable to retrieve information on " + clients.get( i ).getName() + "!" ) ;
921 e2.printStackTrace() ;
926 String[] command = new String[]{ "/usr/bin/scp", working_directory + "/" + _archive,
931 Process proc = Runtime.getRuntime().exec( command ) ;
934 if( proc.exitValue() == 0 )
936 System.out.println( "Initial VM archive successfully sent." ) ;
938 System.err.println( "Initial VM archive not sent!" ) ;
939 // printProcessError( p.getErrorStream() ) ;
940 System.err.println( "Error: " + proc.exitValue() ) ;
941 BufferedReader b = new BufferedReader( new InputStreamReader( proc.getErrorStream() ) ) ;
945 while( (l = b.readLine()) != null )
947 System.err.println( l ) ;
949 } catch( IOException e ) {
950 e.printStackTrace() ;
956 } catch( IOException e ) {
957 System.err.println( "Error during initial VM archive send command: " ) ;
958 e.printStackTrace() ;
961 } catch( InterruptedException e ) {
962 e.printStackTrace() ;
976 ret = clients.get( i ).getStub().deployVM( _name, _archive, _directory ) ;
977 } catch( RemoteException e ) {
978 System.err.println( "Unable to deploy the VM on " + clients.get( i ).getName() + "!" ) ;
979 e.printStackTrace() ;
986 System.out.println( "Initial VM archive successfully deployed on " + clients.get( i ).getName() + "." ) ;
995 System.err.println( "** " + pb + " machine is not deployed!" ) ;
997 System.err.println( "** " + pb + " machine(s) are not deployed!" ) ;
1004 public String getWorkingDirectory()
1006 return working_directory ;
1011 /** La programmation est un art, respectons ceux qui la pratiquent !! **/