--- /dev/null
+package and.hpcvm ;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.rmi.Naming;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+
+
+public class Client extends UnicastRemoteObject implements ServicesClient
+{
+ private static final long serialVersionUID = 1L ;
+
+ private String VmRunCommand ;
+// private String VmRunCommandArg ;
+ private VirtualMachine machine ;
+ private String server_ip ;
+ private int server_port ;
+ private int client_port ;
+ private int dialog_port ;
+ private ServicesServer serverStub ;
+ private ServicesClient myStub ;
+ private PingServer pingServer ;
+ private DialogVMServer dialogVmServer ;
+ private ServerSocket serverSocket ;
+ private String ushell ;
+ private String working_directory ;
+ private int wait_start ;
+ private int max_start_try ;
+ private boolean isRestartedSave ;
+ private long save_interleave ;
+ private long date_last_save ;
+ private SaveProcess saveProcess;
+ private int maxRetryVM ;
+ private int timeRetryVM ;
+
+
+ protected Client() throws RemoteException
+ {
+ super() ;
+ }
+
+
+ @Override
+ public int startVM( int _mode )
+ {
+ if( machine != null && ! machine.getStatus().equalsIgnoreCase( "running" ) )
+ {
+ boolean ret = true ;
+ int retry = 0 ;
+
+ /** Starting VM **/
+ System.out.print( "Starting VM ... " ) ;
+
+ machine.setStatus( "undefined" ) ;
+ if( _mode == 0 )
+ {
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "undefined" ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to inform the server of the VM status!" ) ;
+ e.printStackTrace() ;
+ }
+ }
+
+ String[] command = new String[]{VmRunCommand, "-T", "player", "start",
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name(), "nogui"} ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Virtual machine successfully started." ) ;
+ ret = false ;
+ } else {
+ System.err.println( "Virtual machine not started!" ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to start VM!" ) ;
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during execution of start command: " ) ;
+ e.printStackTrace() ;
+ return 1 ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ return 1 ;
+ }
+
+
+ boolean started = false ;
+ int count = 1 ;
+ ret = true ;
+ retry = 0 ;
+
+ while( ! started )
+ {
+ /** Waiting for VM being started **/
+ try {
+ Thread.sleep( wait_start ) ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ String cmd2 = VmRunCommand + " -T " + " player " + " -gu " + machine.getVmUser() +
+ " -gp " + machine.getVmUserPasswd() + " runScriptInGuest " +
+ working_directory + "/" + machine.getDirectory()
+ + "/" + machine.getVmx_name() + " " + ushell +
+ " \"echo ok\"" ;// + " -noWait " ;
+
+ try {
+ FileWriter fw = new FileWriter( new File( working_directory + "/testStarted.sh" ) ) ;
+ fw.write( cmd2 ) ;
+ fw.flush() ;
+ fw.close() ;
+ } catch( IOException e1 ) {
+ e1.printStackTrace() ;
+ }
+
+ command = new String[]{ ushell, working_directory + "/testStarted.sh"} ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ started = true ;
+// machine.setStatus( "running" ) ;
+// if( _mode == 0 )
+// {
+// LocalHost.Instance().getServerStub().changeStatus(
+// LocalHost.Instance().getIP(), "running" ) ;
+// }
+ ret = false ;
+ } else {
+ System.err.println( "Error while checking if the VM is started!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to check VM!" ) ;
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+// wait_start = wait_start / 2 ;
+ count++ ;
+ }
+ } catch( IOException e ) {
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ if( count == max_start_try && ! started )
+ {
+ System.err.println( "Virtual machine not responding!!" ) ;
+
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "undefined" ) ;
+ } catch( RemoteException e ) {
+ e.printStackTrace() ;
+ }
+
+ stopVM() ;
+
+ return 1 ;
+ } else {
+ try {
+ Thread.sleep( 3000 ) ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+
+ /** Sending the host ip **/
+
+ System.out.print( "Sending host IP to VM ... " ) ;
+
+ String cmd2 = VmRunCommand + " -T " + " player " + " -gu " + machine.getVmUser() +
+ " -gp " + machine.getVmUserPasswd() + " runScriptInGuest " +
+ working_directory + "/" + machine.getDirectory()
+ + "/" + machine.getVmx_name() + " " + ushell +
+ " \"echo " + LocalHost.Instance().getIP() + " " + dialog_port
+ + " > /tmp/vm_host_IP\"" ;
+
+ try {
+ FileWriter fw = new FileWriter( new File( working_directory + "/sendHostIP.sh" ) ) ;
+ fw.write( cmd2 ) ;
+ fw.flush() ;
+ fw.close() ;
+ } catch( IOException e1 ) {
+ e1.printStackTrace() ;
+ }
+
+ command = new String[]{ ushell, working_directory + "/sendHostIP.sh"} ;
+
+ ret = true ;
+ retry = 0 ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "VM received the host IP." ) ;
+ ret = false ;
+ } else {
+ System.err.println( "VM did not received the host IP!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to send information to VM!" ) ;
+
+ stopVM() ;
+
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during execution of runScriptInGuest command: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e) {
+ e.printStackTrace() ;
+ }
+
+ /** Sending the vm ip **/
+
+ System.out.print( "Sending its IP to VM ... " ) ;
+
+ cmd2 = VmRunCommand + " -T " + " player " + " -gu " + machine.getVmUser() +
+ " -gp " + machine.getVmUserPasswd() + " runScriptInGuest " +
+ working_directory + "/" + machine.getDirectory()
+ + "/" + machine.getVmx_name() + " " + ushell +
+ " \"echo " + machine.getIp()
+ + " > /tmp/vm_IP\"" ;
+
+ try {
+ FileWriter fw = new FileWriter( new File( working_directory + "/sendVmIP.sh" ) ) ;
+ fw.write( cmd2 ) ;
+ fw.flush() ;
+ fw.close() ;
+ } catch( IOException e1 ) {
+ e1.printStackTrace() ;
+ }
+
+ command = new String[]{ ushell, working_directory + "/sendVmIP.sh"} ;
+
+ ret = true ;
+ retry = 0 ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "VM received its assigned IP." ) ;
+// return 0 ;
+ ret = false ;
+ machine.setStatus( "running" ) ;
+ } else {
+ System.err.println( "VM did not received its assigned IP!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to send information to VM!" ) ;
+
+ stopVM() ;
+
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during execution of runScriptInGuest command: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ if( _mode == 0 )
+ {
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "running" ) ;
+ } catch (RemoteException e) {
+ System.err.println( "Unable to inform the server of the VM started status!" ) ;
+ e.printStackTrace();
+ }
+ }
+
+ return 0 ;
+ }
+
+ return 1 ;
+ }
+
+ @Override
+ public int stopVM()
+ {
+ if( machine != null && machine.getStatus().equalsIgnoreCase( "stopped" ) )
+ {
+ return 0 ;
+ }
+
+ if( machine != null && ! machine.getStatus().equalsIgnoreCase( "stopped" ) )
+ {
+ System.out.print( "Stopping VM ... " ) ;
+
+ boolean ret = true ;
+ int retry = 0 ;
+
+ machine.setStatus( "undefined" ) ;
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "undefined" ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to inform the server of the VM status!" ) ;
+ e.printStackTrace() ;
+ }
+
+ String[] command = new String[]{VmRunCommand, "-T", "player", "stop",
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name()} ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Virtual machine successfully stopped." ) ;
+ machine.setStatus( "stopped" ) ;
+ ret = false ;
+ } else {
+ System.err.println( "Virtual machine not stopped!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to stop VM!" ) ;
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+
+// return 1 ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during execution of stop command: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ machine.setStatus( "stopped" ) ;
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "stopped" ) ;
+ } catch( RemoteException e1 ) {
+ System.err.println( "Unable to inform the server of the VM stopped status!" ) ;
+ e1.printStackTrace() ;
+ }
+
+ if( ! isRestartedSave )
+ {
+ /** Restoring the original vmx file (necessary after a crash) **/
+ command = new String[]{ "/bin/cp",
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name_normal(),
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name() } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Successfully replaced the VMX file." ) ;
+ return 0 ;
+ } else {
+ System.err.println( "Unsuccessful replacement of the VMX file!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+
+ return 1 ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during VMX file replacement: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ } else {
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ }
+
+ @Override
+ public int suspendVM( int _mode )
+ {
+ if( machine != null && machine.getStatus().equalsIgnoreCase( "suspended" ) )
+ {
+ return 0 ;
+ }
+
+ if( machine != null && ! machine.getStatus().equalsIgnoreCase( "suspended" ) )
+ {
+ System.out.print( "Suspending VM ... " ) ;
+
+ boolean ret = true ;
+ int retry = 0 ;
+
+ machine.setStatus( "undefined" ) ;
+ if( _mode == 0 )
+ {
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "undefined" ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to inform the server of the VM status!" ) ;
+ e.printStackTrace() ;
+ }
+ }
+
+ String[] command = new String[]{VmRunCommand, "-T", "player", "suspend",
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name()} ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Virtual machine successfully suspended." ) ;
+ machine.setStatus( "suspended" ) ;
+ ret = false ;
+ } else {
+ System.err.println( "Virtual machine not suspended!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to suspend VM!" ) ;
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+
+// return 1 ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during execution of suspend command: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ machine.setStatus( "suspended" ) ;
+ if( _mode == 0 )
+ {
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "suspended" ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to inform the server of the VM suspended status!" ) ;
+ e.printStackTrace() ;
+ }
+ }
+
+ return 0 ;
+ }
+
+ return 1 ;
+ }
+
+ @Override
+ public int restartVM()
+ {
+ if( machine != null )
+ {
+ System.out.print( "Restarting VM ... " ) ;
+
+ boolean ret = true ;
+ int retry = 0 ;
+
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "undefined" ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to inform the server of the VM status!" ) ;
+ e.printStackTrace() ;
+ }
+
+ String[] command = new String[]{VmRunCommand, "-T", "player", "reset",
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name()} ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Virtual machine successfully restarted." ) ;
+
+ if( sendSaveOkVM() == 1 ) { return 1 ; }
+
+ ret = false ;
+ return 0 ;
+
+ } else {
+ System.err.println( "Virtual machine not restarted!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to start VM!" ) ;
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+
+// return 1 ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during execution of restart command: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ }
+
+ return 1 ;
+ }
+
+ @Override
+ public int restartVMAfterCrash()
+ {
+ System.out.println( "Restarting VM after a crash ..." ) ;
+
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "undefined" ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to inform the server of the VM status!" ) ;
+ e.printStackTrace() ;
+ }
+
+ if( stopVM() == 0 )
+ {
+ if( machine.deployLastSave() == 0 )
+ {
+ if( isRestartedSave )
+ {
+ // Using the specific vmx file
+ System.out.print( "Changing VMX file after crash ... " ) ;
+
+ String[] command = new String[]{ "/bin/cp",
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name_crash(),
+ working_directory + "/" + machine.getDirectory() + "/" + machine.getVmx_name() } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Successfully replaced the VMX file." ) ;
+ } else {
+ System.err.println( "Unsuccessful replacement of the VMX file!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+
+ return 1 ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during VMX file replacement: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ // Removing lock files
+ System.out.print( "Removing lock files ... " ) ;
+
+ command = new String[]{ "/bin/rm", "-rf",
+ working_directory + "/" + machine.getDirectory()
+ + "/" + machine.getVmx_name() + ".lck" } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Successfully deleted lock files." ) ;
+ } else {
+ System.err.println( "Unsuccessful deletion of lock files!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+
+ return 1 ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during lock files deletion: " ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ /** Retrieving VM assigned IP **/
+ String vmIP = null ;
+
+ try {
+ vmIP = LocalHost.Instance().getServerStub().getAssociatedIP(
+ LocalHost.Instance().getIP() ) ;
+ } catch (RemoteException e) {
+ System.err.println( "Problem while retrieving the VM assigned IP!!" ) ;
+ e.printStackTrace() ;
+ return 1 ;
+ }
+
+ machine.setIp( vmIP ) ;
+
+ isRestartedSave = false ;
+ }
+
+ if( startVM( 0 ) == 0 )
+ {
+ if( sendSaveOkVM() == 0 )
+ {
+ return 0 ;
+ }
+ } else {
+ stopVM() ;
+ }
+ }
+ }
+
+ return 1 ;
+ }
+
+
+ private int sendSaveOkVM()
+ {
+ boolean ret = true ;
+ int retry = 0 ;
+
+ /** Informing the program that it's ok **/
+ System.out.print( "Sending OK signal to the program ... " ) ;
+
+ String cmd2 = VmRunCommand + " -T " + " player " + " -gu " + machine.getVmUser() +
+ " -gp " + machine.getVmUserPasswd() + " runScriptInGuest " +
+ working_directory + "/" + machine.getDirectory()
+ + "/" + machine.getVmx_name() + " " + ushell +
+ " \"echo ok > /tmp/vm_save_ok\"" ;// + " -noWait " ;
+
+ try {
+ FileWriter fw = new FileWriter( new File( working_directory + "/saveOk.sh" ) ) ;
+ fw.write( cmd2 ) ;
+ fw.flush() ;
+ fw.close() ;
+ } catch( IOException e1 ) {
+ e1.printStackTrace() ;
+ }
+
+ String[] command = new String[]{ ushell, working_directory + "/saveOk.sh"} ;
+
+ while( ret )
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Signal successfully sent." ) ;
+ ret = false ;
+ return 0 ;
+ } else {
+ System.err.println( "Signal not sent!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ ret = printProcessError( p ) ;
+
+ if( ! ret )
+ {
+ return 1 ;
+ } else {
+ retry++ ;
+ if( retry >= maxRetryVM )
+ {
+ System.err.println( "Unable to send ok signal to VM!" ) ;
+ return 1 ;
+ }
+ System.out.println( "Retrying (" + retry + ") ... " ) ;
+ Thread.sleep( timeRetryVM ) ;
+ }
+// return 1 ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during ok save signal send command: " ) ;
+ e.printStackTrace() ;
+ return 1 ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ return 1 ;
+ }
+
+ return 1 ;
+ }
+
+
+ @Override
+ public int saveVM()
+ {
+ synchronized( saveProcess ){
+ while( saveProcess.getStatus() )
+ {
+ try {
+ saveProcess.wait() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ }}
+
+ System.out.println( "Saving VM ..." ) ;
+ saveProcess.setStatus( true ) ;
+
+ machine.setStatus( "saving" ) ;
+ try {
+ LocalHost.Instance().getServerStub().changeStatus(
+ LocalHost.Instance().getIP(), "saving" ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to inform the server of the VM status!" ) ;
+ e.printStackTrace() ;
+ }
+
+ String[] command ;
+ String saveName = "" ;
+ boolean error = false ;
+ boolean errorVM = false ;
+
+ if( suspendVM( 1 ) == 1 ) { error = true ; errorVM = true ; }
+
+ if( ! error )
+ {
+ System.out.print( "Creation of the archive ... " ) ;
+ /** Archive creation **/
+ command = new String[]{ "/bin/tar", "-cvf",
+ working_directory + "/" + machine.getName() + "_new_" + machine.getComputationId() + ".tar",
+ working_directory + "/" + machine.getDirectory() } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Archive successfully created." ) ;
+ } else {
+ System.err.println( "Archive not created!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+
+ error = true ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during archive creation command: " ) ;
+ error = true ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ error = true ;
+ }
+
+ /** Compression of the archive **/
+ if( ! error )
+ {
+ System.out.print( "Compression of the archive ... " ) ;
+ command = new String[]{ "/bin/gzip",
+ working_directory + "/" + machine.getName()
+ + "_new_" + machine.getComputationId() + ".tar" } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Archive successfully compressed." ) ;
+ } else {
+ System.err.println( "Archive not compressed!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+
+ error = true ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during archive compression command: " ) ;
+ e.printStackTrace() ;
+ error = true ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ error = true ;
+ }
+ }
+
+
+ /** Restarting VM **/
+ if( errorVM || startVM( 0 ) == 1 ) { error = true ; }
+
+
+ /** Sending ok save signal **/
+ if( ! error )
+ {
+ if( sendSaveOkVM() == 1 ) { error = true ; }
+ }
+
+// /** Deletion of the tar archive **/
+// if( ! error )
+// {
+// command = new String[]{ "/bin/rm",
+// working_directory + "/" + machine.getName()
+// + "_new_" + machine.getComputationId() + ".tar" } ;
+//
+// try {
+// Process p = Runtime.getRuntime().exec( command ) ;
+// p.waitFor() ;
+//
+// if( p.exitValue() == 0 )
+// {
+// System.out.println( "Archive (not compressed) successfully deleted." ) ;
+// } else {
+// System.err.println( "Archive (not compressed) not deleted!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+//
+// error = true ;
+// }
+// } catch( IOException e ) {
+// System.err.println( "Error during archive (not compressed) deletion command: " ) ;
+// e.printStackTrace() ;
+// error = true ;
+// } catch( InterruptedException e ) {
+// e.printStackTrace() ;
+// error = true ;
+// }
+// }
+
+ saveName = working_directory + "/" + machine.getName() + "_new_"
+ + machine.getComputationId() + ".tar.gz" ;
+
+ /** Sending save to neighbor **/
+ if( ! error )
+ {
+ ArrayList<String> sn = machine.getSaveNeighbors() ;
+
+ for( int i = 0 ; i < sn.size() ; i++ )
+ {
+ System.out.print( "Sending save to " + sn.get( i ) + " ... " ) ;
+ command = new String[]{ "/usr/bin/scp", saveName,
+ sn.get( i ) + ":"
+ + working_directory } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Archive successfully sent." ) ;
+ } else {
+ System.err.println( "Archive not sent!" ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+
+ error = true ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during archive send command: " ) ;
+ e.printStackTrace() ;
+ error = true ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ error = true ;
+ }
+ }
+ }
+ }
+
+ /** Informing the server the save is done **/
+ if( ! error )
+ {
+ try {
+ LocalHost.Instance().getServerStub().saveOk( LocalHost.Instance().getIP(), saveName ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Problem while informing the server about the save state!" ) ;
+ e.printStackTrace() ;
+ }
+
+ synchronized( saveProcess ) {
+ saveProcess.setStatus( false ) ;
+ try {
+ saveProcess.notifyAll() ;
+ } catch( Exception e ) {}}
+
+ return 0 ;
+ }
+
+ synchronized( saveProcess ) {
+ saveProcess.setStatus( false ) ;
+ try {
+ saveProcess.notifyAll() ;
+ } catch( Exception e ) {}}
+
+ return 1 ;
+ }
+
+
+ @Override
+ public int reloadConfig()
+ {
+ System.out.println( "Reloading configuration ... " ) ;
+
+ // TODO !!!
+ return 0 ;
+ }
+
+ public void init( String _server_ip, int _server_port, int _client_port, int _dialog_port )
+ {
+ System.out.println( "Initialisation Client ... " ) ;
+ System.out.println( "IP " + LocalHost.Instance().getIP() ) ;
+
+ server_ip = _server_ip ;
+ server_port = _server_port ;
+ client_port = _client_port ;
+ dialog_port = _server_port + 1 ; // _dialog_port ;
+
+ serverStub = null ;
+ saveProcess = new SaveProcess() ;
+
+ machine = new VirtualMachine() ;
+
+ VmRunCommand = "/usr/bin/vmrun" ;
+// VmRunCommandArg = "-T player" ;
+
+// vm_user = "mpi" ;
+// vm_user_passwd = "mpi" ;
+ ushell = "/bin/bash" ;
+ working_directory = "/localhome/vmware" ;
+
+ wait_start = 15000 ;
+ max_start_try = 10 ;
+
+ maxRetryVM = 10 ;
+ timeRetryVM = 10000 ;
+
+ save_interleave = 30 * 60 * 1000 ;
+ date_last_save = 0 ;
+
+ isRestartedSave = false ;
+
+ /** Connection to server **/
+ try {
+ serverStub = (ServicesServer) Naming.lookup( "rmi://"
+ + server_ip + ":" + server_port + "/Server" ) ;
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ } catch (NotBoundException e) {
+ e.printStackTrace();
+ }
+
+ if( serverStub == null )
+ {
+ System.err.println( "Unable to connect to server!!" ) ;
+ System.err.println( "Server IP: " + server_ip + " -- server port: " + server_port ) ;
+
+ System.exit( 1 ) ;
+ }
+
+ System.out.println( "Connected to server " + server_ip + " on port " + server_port + "." ) ;
+
+// LocalHost.Instance().setServerIP( server_ip ) ;
+ LocalHost.Instance().setServerStub( serverStub ) ;
+
+
+ /** Creating the local server **/
+ exportObject() ;
+
+ /** Starting all threads **/
+ start() ;
+ }
+
+ private void exportObject()
+ {
+// ServicesClient ref = null ;
+ Registry reg = null ;
+
+ try
+ {
+ while( true )
+ {
+ reg = LocateRegistry.getRegistry( client_port ) ;
+
+ String tab[] = reg.list() ;
+
+ System.out.println( "There is an existing RMI Registry on port " +
+ client_port + " with " + tab.length + " entries!" ) ;
+ for( int i = 0 ; i < tab.length ; i++ )
+ {
+ try {
+ if( UnicastRemoteObject.unexportObject( Naming.lookup(tab[i]), true ) )
+ {
+ System.out.println( "Register successfuly deleted!" ) ;
+ } else {
+ System.err.println( "Register undeleted !!!" ) ;
+ }
+ } catch( Exception e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+ } catch( RemoteException e ) {
+ }
+
+ try {
+ if ( System.getSecurityManager() == null )
+ {
+ System.setSecurityManager( new SecurityManager() ) ;
+ }
+
+ LocateRegistry.createRegistry( client_port ) ;
+ LocateRegistry.getRegistry( client_port ).rebind( "Client", this ) ;
+ myStub = (ServicesClient) Naming.lookup( "rmi://"
+ + LocalHost.Instance().getIP() + ":" + client_port
+ + "/Client" ) ;
+ } catch( Exception e ) {
+ System.err.println( "Error in Client.exportObject() when creating local services:" + e ) ;
+ System.err.println( "Exit from Client.exportObject" ) ;
+ System.exit( 1 ) ;
+ }
+
+ LocalHost.Instance().setStub( myStub ) ;
+ }
+
+
+ private boolean printProcessError( Process _p )
+ {
+ boolean ret = false ;
+
+ if( _p != null )
+ {
+ System.err.println( "Error: " + _p.exitValue() ) ;
+ BufferedReader br = new BufferedReader( new InputStreamReader( _p.getErrorStream() ) ) ;
+ String line ;
+ try {
+ while( (line = br.readLine()) != null )
+ {
+ System.err.println( line ) ;
+ if( line.contains( "egmentation" ) )
+ {
+ ret = true ;
+ }
+ }
+ } catch( IOException e ) {
+ e.printStackTrace() ;
+ }
+ }
+
+ return ret ;
+ }
+
+
+ @Override
+ public int start()
+ {
+ /** Registering on server **/
+ Integer ret = 0 ;
+ try {
+ ret = LocalHost.Instance().getServerStub().register( LocalHost.Instance().getStub() );
+ } catch (RemoteException e1) {
+ e1.printStackTrace();
+ return 1 ;
+ }
+
+ switch( ret )
+ {
+ case 0: System.out.println( "Successfully registered on server." ) ; break ;
+ case 1: System.err.println( "Problem on server while registreting!" ) ; return 1 ;
+ case 2: System.out.println( "Already registered on server!" ) ; break ;
+ }
+
+ /** Retrieving VM assigned IP **/
+ String vmIP = null ;
+
+ try {
+ vmIP = LocalHost.Instance().getServerStub().getAssociatedIP(
+ LocalHost.Instance().getIP() ) ;
+ } catch (RemoteException e) {
+ System.err.println( "Problem while retrieving the VM assigned IP!!" ) ;
+ e.printStackTrace() ;
+ return 1 ;
+ }
+
+ machine.setIp( vmIP ) ;
+
+ System.out.println( "Assigned IP address for the VM: " + vmIP ) ;
+
+
+ /** Starting alive ping to server **/
+ pingServer = new PingServer() ;
+ pingServer.start() ;
+
+ /** Starting socket server for VM dialog **/
+ dialogVmServer = new DialogVMServer() ;
+ dialogVmServer.start() ;
+
+ return 0 ;
+ }
+
+
+ private class PingServer extends Thread
+ {
+ private boolean run ;
+
+ PingServer()
+ {
+ run = true ;
+ }
+
+ protected void stopPing() { run = false ; }
+
+ @Override
+ public void run()
+ {
+ while( run )
+ {
+ try {
+ LocalHost.Instance().getServerStub().ping( LocalHost.Instance().getIP() ) ;
+ } catch (RemoteException e1) {
+ e1.printStackTrace();
+ }
+
+ try {
+ Thread.sleep( 2000 ) ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+ }
+
+
+ private class DialogVMServer extends Thread
+ {
+ private boolean run ;
+ private Socket socket ;
+ private ArrayList<DialogVM> dialogs = new ArrayList<DialogVM>() ;
+
+ DialogVMServer()
+ {
+ run = true ;
+ }
+
+ protected void stopDialogVMServer()
+ {
+ run = false ;
+
+ if( serverSocket != null )
+ {
+ try {
+ serverSocket.close() ;
+// socket = serverSocket.accept() ;
+
+ for( int i = 0 ; i < dialogs.size() ; i++ )
+ {
+ dialogs.get( i ).stopDialogVM() ;
+ }
+
+ } catch( IOException e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+
+
+ @Override
+ public void run()
+ {
+ try {
+ serverSocket = new ServerSocket( 0 ) ;
+ dialog_port = serverSocket.getLocalPort() ;
+
+ System.out.println( "SocketServer listening on port " + dialog_port ) ;
+ } catch( IOException e ) {
+ System.err.println( "Unable to launch the SocketServer on port " + dialog_port + "!" ) ;
+ e.printStackTrace() ;
+
+ run = false ;
+ }
+
+ while( run )
+ {
+ try {
+ socket = serverSocket.accept() ;
+
+ dialogs.add( new DialogVM( socket ) ) ;
+ dialogs.get( dialogs.size() - 1 ).start() ;
+ } catch( IOException e ) {
+ System.err.println( "Problem with the accept function!" ) ;
+ e.printStackTrace() ;
+ }
+ }
+ }
+ }
+
+
+ private class DialogVM extends Thread
+ {
+ private boolean run ;
+ private Socket socket ;
+ private BufferedReader reader ;
+ private String line ;
+
+ DialogVM( Socket _socket ) { run = true ; socket = _socket ; }
+
+ protected void stopDialogVM()
+ {
+ run = false ;
+
+ try {
+ reader.close() ; reader = null ;
+ socket.close() ; socket = null ;
+ } catch( IOException e ) {
+ e.printStackTrace() ;
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ try {
+ reader = new BufferedReader( new InputStreamReader( socket.getInputStream() ) ) ;
+ } catch( IOException e ) {
+ System.err.println( "Unable to open a dialog socket with the VM!" ) ;
+ e.printStackTrace();
+ stopDialogVM() ;
+ }
+
+ while( run )
+ {
+ try {
+ line = null ;
+
+ if( reader != null )
+ {
+ line = reader.readLine() ;
+ }
+
+ /** VM is starting -- retrieving informations **/
+ if( run && line != null && line.equalsIgnoreCase( "infos" ) )
+ {
+ /* Receiving name */
+ machine.setName( reader.readLine() ) ;
+
+ /* Receiving IP */
+ String ip = reader.readLine() ;
+ if( ! ip.equalsIgnoreCase( machine.getIp() ) )
+ {
+ System.err.println( "VM IP not well configured!!" ) ;
+ }
+
+ /* Close streams */
+ reader.close() ; reader = null ;
+ socket.close() ; socket = null ;
+
+ run = false ;
+ }
+
+ /** It's time to do a save **/
+ if( run && line != null && line.equalsIgnoreCase( "save" ) )
+ {
+ try {
+ machine.setComputationId( Integer.parseInt( reader.readLine() ) ) ;
+ } catch( Exception e ) {
+ System.err.println( "Problem while reading the computation id!" ) ;
+ e.printStackTrace() ;
+ }
+
+ if( (System.currentTimeMillis() - date_last_save) > save_interleave )
+ {
+ date_last_save = System.currentTimeMillis() ;
+
+ /* Close streams */
+ reader.close() ; reader = null ;
+ socket.close() ; socket = null ;
+
+ run = false ;
+
+ /* Starting the VM save */
+ saveVM() ;
+ } else {
+ sendSaveOkVM() ;
+ }
+ }
+
+
+ /** Computation is done, we can shutdown the VM **/
+ if( run && line != null && line.equalsIgnoreCase( "quit" ) )
+ {
+ try {
+ Thread.sleep( 5000 ) ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+
+ /* Close streams */
+ reader.close() ; reader = null ;
+ socket.close() ; socket = null ;
+
+ run = false ;
+
+ stopVM() ;
+ }
+
+ } catch( IOException e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void stop()
+ {
+ stopVM() ;
+
+ pingServer.stopPing() ;
+
+ dialogVmServer.stopDialogVMServer() ;
+
+ // unexportObject ??
+
+ System.exit( 0 ) ;
+ }
+
+ @Override
+ public String getIPHost()
+ {
+ return LocalHost.Instance().getIP() ;
+ }
+
+ @Override
+ public String getName()
+ {
+ return LocalHost.Instance().getName() ;
+ }
+
+
+ @Override
+ public void saveOk()
+ {
+ String save_name = "VmTest_" + machine.getComputationId() +
+ "_last.tar.gz" ;
+
+ String save_new = working_directory + "/" + machine.getName() + "_new_"
+ + machine.getComputationId() + ".tar.gz" ;
+
+ String[] command = new String[]{ "/bin/mv",
+ save_new, save_name } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Last save OK" ) ;
+ machine.setSave_last( save_name ) ;
+ } else {
+ System.err.println( "Last save NOK!" ) ;
+ System.err.println( "Error: " ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during last archive move:" ) ;
+ e.printStackTrace() ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ }
+
+ @Override
+ public void setSavingNeighbor( String _sn ) throws RemoteException
+ {
+ if( _sn != null && _sn.length() > 0 )
+ {
+ ArrayList<String> as = new ArrayList<String>() ;
+ as.add( _sn ) ;
+
+ System.out.println( "Save neighbor: " + _sn ) ;
+
+ machine.setSaveNeighbors( as ) ;
+ }
+ }
+
+ @Override
+ public int retrieveSave( String _saveName ) throws RemoteException
+ {
+ if( _saveName != null )
+ {
+ if( ! _saveName.equalsIgnoreCase( "none" ) )
+ {
+ machine.setSave_last( _saveName ) ;
+ } else {
+ System.err.println( "I have no saving neighbor to contact!!" ) ;
+ return 1 ;
+ }
+
+ // TODO NEIGHBORS !!!!
+ //System.out.println( "!!!! NEIGHBORS !!!!!" ) ;
+ System.out.print( "Retrieving a save on " + machine.getSaveNeighbors().get( 0 ) + " ..." ) ;
+ String[] command = new String[]{ "/usr/bin/scp",
+ machine.getSaveNeighbors().get( 0 ) + ":"
+ + working_directory + "/" + machine.getSave_last(),
+ working_directory } ;
+
+ try {
+ Process p = Runtime.getRuntime().exec( command ) ;
+ p.waitFor() ;
+
+ if( p.exitValue() == 0 )
+ {
+ System.out.println( "Archive successfully retrieved." ) ;
+ isRestartedSave = true ;
+ return 0 ;
+ } else {
+ System.err.println( "Archive not retrieved!" ) ;
+ System.err.println( "Error: " ) ;
+// printProcessError( p.getErrorStream() ) ;
+ printProcessError( p ) ;
+// error = true ;
+ }
+ } catch( IOException e ) {
+ System.err.println( "Error during archive retrieve command: " ) ;
+ e.printStackTrace() ;
+// error = true ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+// error = true ;
+ }
+ }
+
+ return 1 ;
+
+ }
+
+ @Override
+ public String getIPVM() throws RemoteException
+ {
+ if( machine != null )
+ {
+ return machine.getIp() ;
+ }
+
+ return null ;
+ }
+
+
+ @Override
+ public void setIPVM( String _ipVM ) throws RemoteException
+ {
+ if( _ipVM != null && ! _ipVM.isEmpty() )
+ {
+ System.out.println( "The VM IP is now: " + _ipVM ) ;
+ machine.setIp( _ipVM ) ;
+ }
+ }
+
+
+ private class SaveProcess
+ {
+ boolean status ;
+
+ SaveProcess()
+ {
+ status = false ;
+ }
+
+ protected boolean getStatus() { return status ; }
+
+ protected void setStatus( boolean _b ) { status = _b ; }
+ }
+
+}
+
+
+/** La programmation est un art, respectons ceux qui la pratiquent !! **/
--- /dev/null
+package and.hpcvm ;
+
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+
+public class Server extends UnicastRemoteObject implements ServicesServer
+{
+ private class DiscCount
+ {
+ private int nb ;
+
+ DiscCount() { nb = 0 ; }
+
+ protected void inc() { nb++ ; }
+
+ protected void dec() {
+ if( nb > 0 )
+ {
+ nb-- ;
+ }
+ }
+
+ protected int getNb() { return nb ; }
+ }
+
+
+ private class ConnectedClient
+ {
+ private ServicesClient stub ;
+ private int timeout ;
+ private Status state ;
+ private String ip ;
+ private String name ;
+ private ComputingClient cl ;
+
+ ConnectedClient( ServicesClient _stub )
+ {
+ stub = _stub ;
+ timeout = 0 ;
+ state = new Status() ;
+ state.setStatus( "connected" ) ;
+ try {
+ ip = stub.getIPHost() ;
+ name = stub.getName() ;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ cl = null ;
+ }
+
+ protected ServicesClient getStub() { return stub ; }
+
+ protected void setStub( ServicesClient _stub ) { stub = _stub ; }
+
+ protected int getTimeout() { return timeout ; }
+
+ protected void incTimeout() { timeout++ ; }
+
+ protected void resetTimeout() { timeout = 0 ; }
+
+ protected String getStatus() { return state.getStatus() ; }
+
+ protected void setStatus( String _state ) { state.setStatus( _state ) ; }
+
+ protected String getIP() { return ip ; }
+
+ protected String getName() { return name ; } ;
+
+ protected void setComputingClient( ComputingClient _cl ) { cl = _cl ; }
+
+ protected ComputingClient getComputingClient() { return cl ; }
+ }
+
+
+ private class ComputingClient
+ {
+ private ConnectedClient client ;
+ private boolean save_status ;
+ private String save_neighbor ;
+ private String lastSaveName ;
+
+ ComputingClient( ConnectedClient cl )
+ {
+ client = cl ;
+ save_status = false ;
+ save_neighbor = "none" ;
+ lastSaveName = "none" ;
+ }
+
+ protected ConnectedClient getClient() { return client ; }
+
+ protected boolean getSaveStatus(){ return save_status ; }
+
+ protected void setSaveStatus( boolean _status ) { save_status = _status ; }
+
+ protected void setSaveNeighbor( String _sn )
+ {
+ if( _sn != null && ! _sn.isEmpty() )
+ {
+ save_neighbor = _sn ;
+
+ try {
+ client.getStub().setSavingNeighbor( _sn ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Error while setting save neighbor on " +
+ client.getName() + "(" + client.getIP() + ")!" ) ;
+ e.printStackTrace() ;
+ }
+ }
+ }
+
+ protected String getSaveNeighbor() { return save_neighbor ; }
+
+ public void setLastSave( String _saveName )
+ {
+ lastSaveName = _saveName ;
+ }
+
+ public String getLastSave() { return lastSaveName ; }
+
+ }
+
+
+ private class IPAssociation
+ {
+ private String vmIP ;
+ private String hostIP ;
+
+ IPAssociation()
+ {
+ vmIP = null ;
+ hostIP = null ;
+ }
+
+ protected void setVmIP( String _vmIP )
+ {
+ vmIP = _vmIP ;
+ }
+
+ protected void setHostIP( String _hostIP )
+ {
+ hostIP = _hostIP ;
+ }
+
+ protected String getVmIP()
+ {
+ return vmIP ;
+ }
+
+ protected String getHostIP()
+ {
+ return hostIP ;
+ }
+ }
+
+
+
+ private static final long serialVersionUID = 1L ;
+ private int port ;
+ private ArrayList<ConnectedClient> clients ;
+ private ArrayList<ComputingClient> computingClients ;
+ private int max_timeout ;
+ private ConnectedMonitor monitor ;
+ private DiscCount counter ;
+ private ArrayList<IPAssociation> vmIPs ;
+
+
+ protected Server() throws RemoteException
+ {
+ super() ;
+ }
+
+
+
+ @Override
+ public Integer register( ServicesClient _stub )
+ {
+ if( _stub != null )
+ {
+ String ip = "" ;
+ try {
+ ip = _stub.getIPHost() ;
+ } catch (RemoteException e) {
+ e.printStackTrace() ;
+ return 1 ;
+ }
+
+ boolean exists = false ;
+ int i ;
+
+ for( i = 0 ; i < clients.size() ; i++ )
+ {
+ if( ip.equals( clients.get( i ).getIP() ) )
+ {
+ exists = true ;
+ System.out.println( "Client already connected!" ) ;
+ break ;
+ }
+ }
+
+ if( exists )
+ {
+ System.out.println( "The client stub will be replaced." ) ;
+ clients.get( i ).setStub( _stub ) ;
+ System.out.println( "(reconnection of " + clients.get( i ).getName() + ")" ) ;
+ return 2 ;
+ } else {
+ System.out.println( "New connection!" ) ;
+ clients.add( new ConnectedClient( _stub ) ) ;
+ System.out.println( "(connection of " + clients.get( clients.size() - 1 ).getName() + ")" ) ;
+ generateVmIP( ip ) ;
+
+ if( clients.size() == 0 )
+ {
+ System.out.println( "There is no client connected." ) ;
+ } else if( clients.size() == 1 ) {
+ System.out.println( "There is one client connected." ) ;
+ } else {
+ System.out.println( "There are " + clients.size() + " clients connected." ) ;
+ }
+
+ return 0 ;
+ }
+ }
+
+ return 1 ;
+ }
+
+
+ private void generateVmIP( String _ip )
+ {
+ if( _ip != null && ! _ip.equals( "" ) )
+ {
+ for( int i = 0 ; i < vmIPs.size() ; i++ )
+ {
+ if( vmIPs.get( i ).getHostIP() == null )
+ {
+ vmIPs.get( i ).setHostIP( _ip ) ;
+
+ break ;
+ }
+ }
+ }
+ }
+
+
+ @Override
+ public void ping( String _ip )
+ {
+ if( _ip != null )
+ {
+ for( int i = 0 ; i < clients.size() ; i++ )
+ {
+ if( _ip.equals( clients.get( i ).getIP() ) )
+ {
+ clients.get( i ).resetTimeout() ;
+ break ;
+ }
+ }
+ }
+ }
+
+
+ @Override
+ public void changeStatus( String _ip, String _status )
+ {
+ if( _ip != null && _status != null )
+ {
+ for( int i = 0 ; i < clients.size() ; i++ )
+ {
+ if( _ip.equals( clients.get( i ).getIP() ) )
+ {
+ clients.get( i ).setStatus( _status ) ;
+ System.out.println( "Client " + clients.get( i ).getName() + " changed its status to: " + _status ) ;
+ break ;
+ }
+ }
+ }
+ }
+
+
+ public void init( int _port )
+ {
+ port = _port ;
+ max_timeout = 4 ;
+
+ clients = new ArrayList<Server.ConnectedClient>() ;
+ computingClients = new ArrayList<Server.ComputingClient>() ;
+ monitor = null ;
+
+ exportObject() ;
+
+ vmIPs = new ArrayList<IPAssociation>() ;
+ // TODO initialisation of VM IPs
+ for( int i = 2 ; i < 101 ; i++ )
+ {
+ vmIPs.add( new IPAssociation() ) ;
+ vmIPs.get( vmIPs.size() - 1 ).setVmIP( "10.11.10." + i ) ;
+ }
+
+ clients = new ArrayList<Server.ConnectedClient>() ;
+
+ counter = new DiscCount() ;
+
+ monitor = new ConnectedMonitor() ;
+ monitor.start() ;
+ }
+
+
+ public void stop()
+ {
+ if( monitor != null ) { monitor.stopMonitor() ; }
+
+ for( int i = 0 ; i < clients.size() ; i++ )
+ {
+ try {
+ clients.get( i ).getStub().stop() ;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ // unexportObject ?
+
+ System.exit( 0 ) ;
+ }
+
+
+ private void exportObject()
+ {
+ ServicesServer ref = null ;
+ Registry reg = null ;
+
+ try
+ {
+ while( true )
+ {
+ reg = LocateRegistry.getRegistry( port ) ;
+
+ String tab[] = reg.list() ;
+
+ System.out.println( "There is an existing RMI Registry on port " +
+ port + " with " + tab.length + " entries!" ) ;
+ for( int i = 0 ; i < tab.length ; i++ )
+ {
+ try {
+ if( UnicastRemoteObject.unexportObject( Naming.lookup(tab[i]), true ) )
+ {
+ System.out.println( "Register successfuly deleted!" ) ;
+ } else {
+ System.err.println( "Register undeleted !!!" ) ;
+ }
+ } catch( Exception e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+ } catch( RemoteException e ) {
+ }
+
+ try {
+ if ( System.getSecurityManager() == null )
+ {
+ System.setSecurityManager( new SecurityManager() ) ;
+ }
+
+ LocateRegistry.createRegistry( port ) ;
+ LocateRegistry.getRegistry( port ).rebind( "Server", this ) ;
+ ref = (ServicesServer) Naming.lookup( "rmi://"
+ + LocalHost.Instance().getIP() + ":" + port
+ + "/Server" ) ;
+ } catch ( Exception e ) {
+ System.err.println( "Error in Server.exportObject() when creating local services:" + e ) ;
+ System.err.println( "Exit from Server.exportObject" ) ;
+ System.exit( 1 ) ;
+ }
+
+ LocalHost.Instance().setServerStub( ref ) ;
+
+ System.out.println( "Server launched on IP " + LocalHost.Instance().getIP() +
+ " on port " + port + "." ) ;
+ }
+
+ /** Fault manager thread **/
+ private class FaultManager extends Thread
+ {
+ ConnectedClient cl ;
+
+ FaultManager( ConnectedClient _cl )
+ {
+ cl = _cl ;
+ }
+
+ @Override
+ public void run()
+ {
+ synchronized( counter ){
+ counter.inc() ;}
+ System.out.println("ici");
+ if( cl != null && cl.getStatus().equalsIgnoreCase( "running" ) ||
+ cl.getStatus().equalsIgnoreCase( "saving" ) )
+ {
+ System.out.println("ok");
+ ComputingClient cc = cl.getComputingClient() ;
+ String ipDead = cc.getClient().getIP() ;
+
+ boolean ok = false ;
+
+ for( int i = 0 ; i < clients.size() ; i++ )
+ {
+ if( clients.get( i ).getStatus().equalsIgnoreCase( "connected" ) )
+ {
+// int res = 1 ;
+// try {
+// res = clients.get( i ).getStub().startVM() ;
+// } catch( RemoteException e ) {
+// e.printStackTrace();
+// }
+//
+// if( res == 0 )
+// {
+ //clients.get(i).setStatus( "running" ) ;
+
+ int pos = computingClients.indexOf( cc ) ;
+ if( pos == -1 )
+ {
+ System.err.println( "Dead client not found in the computing clients list!" ) ;
+ } else {
+ System.out.println( "Trying to replace " + cc.getClient().getName() + " with " +
+ clients.get(i).getName() + " ... " ) ;
+
+ ComputingClient ccl = new ComputingClient( clients.get(i) ) ;
+ clients.get( i ).setComputingClient( ccl ) ;
+ String sn = computingClients.get( pos ).getSaveNeighbor() ;
+ ccl.setSaveNeighbor( sn ) ;
+ computingClients.set( pos, ccl ) ;
+// computingClients.get( pos ).setSaveNeighbor( sn ) ;
+
+
+ int res = 1 ;
+ try {
+ res = computingClients.get( pos ).getClient().getStub().
+ retrieveSave( computingClients.get(i).getLastSave() ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to indicate to client to retrieve last save!" ) ;
+ e.printStackTrace() ;
+ }
+
+ if( res == 0 )
+ {
+ ok = true ;
+
+ // replace dead client in vmIPs
+ for( int j = 0 ; j < vmIPs.size() ; j++ )
+ {
+ if( vmIPs.get( j ).getHostIP().equalsIgnoreCase( ipDead ) )
+ {
+ String vmIP = vmIPs.get( j ).getVmIP() ;
+ vmIPs.get( j ).setHostIP( computingClients.get( pos ).getClient().getIP() ) ;
+
+ try {
+ computingClients.get( pos ).getClient().getStub().setIPVM( vmIP ) ;
+ } catch( RemoteException e ) {
+ System.err.println( "Unable to set the new VM IP on the replacing client!" ) ;
+ e.printStackTrace() ;
+ }
+ break ;
+ }
+ }
+
+ System.out.println( "Successful redeployment of the VM." ) ;
+ } else {
+ System.err.println( "Unable to deploy the save on the new computing client!" ) ;
+ }
+ }
+// } else {
+// System.err.println( "Problem while launching the VM on "
+// + clients.get(i).getName() + "!" ) ;
+// }
+
+ if( ok )
+ {
+ System.out.println( "Dead client successfully replaced." ) ;
+ // restart vms
+ break ;
+ } else {
+ System.err.println( "Dead client not replaced!!" ) ;
+ }
+ }
+ }
+ }
+
+ try {
+ synchronized( counter ) {
+ counter.dec() ;
+ counter.notifyAll() ;}
+ } catch( Exception e ) {}
+ }
+ }
+
+
+ /** Monitoring thread **/
+ private class ConnectedMonitor extends Thread
+ {
+ boolean run ;
+
+ ConnectedMonitor()
+ {
+ run = true ;
+ }
+
+ protected void stopMonitor() { run = false ; }
+
+ @Override
+ public void run()
+ {
+ boolean change ;
+
+ while( run )
+ {
+ change = false ;
+ Iterator<ConnectedClient> it = clients.iterator() ;
+ int nb_disconnections = 0 ;
+ int nb_disconnections_computing = 0 ;
+
+ while( it.hasNext() )
+ {
+ ConnectedClient cl = it.next() ;
+ cl.incTimeout() ;
+
+ if( cl.getTimeout() > max_timeout )
+ {
+ System.out.println( "Disconnection of " + cl.getName() ) ;
+ if( cl.getStatus().equalsIgnoreCase( "running" ) || cl.getStatus().equalsIgnoreCase( "saving" ) )
+ {
+ System.out.println( "A VM was running on it!!" ) ;
+ System.out.println( "I will redeploy a save and restart all VM ..." ) ;
+
+// for( int i = 0 ; i < computingClients.size() ; i++ )
+// {
+// if( computingClients.get( i ).getClient().getIP().equals( cl.getIP() ) )
+// {
+// computingClients.remove( i ) ;
+// break ;
+// }
+// }
+
+ new Server.FaultManager( cl ).start() ;
+ nb_disconnections_computing++ ;
+ } else {
+ System.out.println( "There was no VM running on it." ) ;
+ System.out.println( "Maybe it will come back later :)" ) ;
+ }
+
+ it.remove() ;
+ nb_disconnections++ ;
+ change = true ;
+ }
+ }
+
+ if( change )
+ {
+ if( clients.size() == 0 )
+ {
+ System.out.println( "There is no client connected." ) ;
+ } else if( clients.size() == 1 ) {
+ System.out.println( "There is one client connected." ) ;
+ } else {
+ System.out.println( "There are " + clients.size() + " clients connected." ) ;
+ }
+ }
+
+
+ if( nb_disconnections_computing > 0 )
+ {
+ System.out.println( "I will redeploy save and restart VMs ..." ) ;
+
+ synchronized( counter )
+ {
+ if( counter.getNb() > 0 )
+ {
+ System.out.println( "... waiting all redeployments done ..." ) ;
+ }
+
+ while( counter.getNb() != 0 )
+ {
+ try {
+ counter.wait() ; // !!!!! synchro
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+
+ for( int i = 0 ; i < computingClients.size() ; i++ )
+ {
+ final ServicesClient sc = computingClients.get( i ).getClient().getStub() ;
+
+ new Thread( new Runnable() {
+
+ @Override
+ public void run()
+ {
+ try {
+ sc.restartVMAfterCrash() ;
+ } catch( RemoteException e ) {
+ e.printStackTrace() ;
+ }
+ }
+ } ).start() ;
+ }
+ }
+
+ try
+ {
+ Thread.sleep( 2000 ) ;
+ } catch( InterruptedException e ) {
+ e.printStackTrace() ;
+ }
+ }
+ }
+ }
+
+ @Override
+ public Integer saveOk( String _ip, String _saveName )
+ {
+ int i ;
+ for( i = 0 ; i < computingClients.size() ; i ++ )
+ {
+ if( computingClients.get( i ).getClient().getIP().equalsIgnoreCase( _ip ) )
+ {
+ computingClients.get( i ).setLastSave( _saveName ) ;
+ computingClients.get( i ).setSaveStatus( true ) ;
+ break ;
+ }
+ }
+
+
+ boolean all_ok = true ;
+ i = 0 ;
+
+ while( all_ok && i < computingClients.size() )
+ {
+ all_ok = all_ok & computingClients.get( i ).getSaveStatus() ;
+ i++ ;
+ }
+
+ if( all_ok )
+ {
+ for( i = 0 ; i < computingClients.size() ; i++ )
+ {
+ try {
+ computingClients.get( i ).getClient().getStub().saveOk() ;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ computingClients.get( i ).setSaveStatus( false ) ;
+ }
+ }
+
+ return 0 ;
+ }
+
+
+
+ @Override
+ public ArrayList<ServicesClient> startApplication( int _nb )
+ {
+ int nb = clients.size() - computingClients.size() ;
+
+ if( nb > _nb )
+ {
+ ArrayList<ServicesClient> ac = new ArrayList<ServicesClient>() ;
+ ArrayList<ComputingClient> tmp = new ArrayList<Server.ComputingClient>() ;
+
+ int i = 0 ;
+
+ while( i < clients.size() && ac.size() < _nb )
+ {
+ if( clients.get(i).getStatus().equalsIgnoreCase( "connected" ) )
+ {
+ int res = 1 ;
+ try {
+ res = clients.get( i ).getStub().startVM( 0 ) ;
+ } catch( RemoteException e ) {
+ e.printStackTrace();
+ }
+
+ if( res == 0 )
+ {
+ ac.add( clients.get( i ).getStub() ) ;
+ clients.get( i ).setStatus( "running" ) ;
+ ComputingClient cl = new ComputingClient( clients.get( i ) ) ;
+ clients.get( i ).setComputingClient( cl ) ;
+ computingClients.add( cl ) ;
+ tmp.add( cl ) ;
+ } else {
+ System.err.println( "Problem while launching the VM on "
+ + clients.get(i).getName() + "!" ) ;
+ }
+ }
+
+ i++ ;
+ }
+
+ if( ac.size() == _nb )
+ {
+ int index, index2 ;
+ /* Choosing save neighbors */
+ for( i = 0 ; i < tmp.size() ; i++ )
+ {
+ if( i == tmp.size() - 1 )
+ {
+ index = computingClients.indexOf( tmp.get( i ) ) ;
+ index2 = computingClients.indexOf( tmp.get( 0 ) ) ;
+
+ if( index == -1 || index2 == -1 )
+ {
+ System.err.println( "Problem in ComputingClients list!" ) ;
+ } else {
+ computingClients.get( index ).setSaveNeighbor( computingClients.get( index2 ).getClient().getIP() ) ;
+ }
+ } else {
+ index = computingClients.indexOf( tmp.get( i ) ) ;
+ index2 = computingClients.indexOf( tmp.get( i + 1 ) ) ;
+
+ if( index == -1 || index2 == -1 )
+ {
+ System.err.println( "Problem in ComputingClients list!" ) ;
+ } else {
+ computingClients.get( index ).setSaveNeighbor( computingClients.get( index2 ).getClient().getIP() ) ;
+ }
+ }
+ }
+ }
+
+ /* Cleaning */
+ tmp.clear() ;
+ tmp = null ;
+
+ return ac ;
+ }
+
+ return null ;
+ }
+
+
+
+ @Override
+ public void endApplication()
+ {
+ Iterator<ComputingClient> it = computingClients.iterator() ;
+
+ while( it.hasNext() )
+ {
+ ComputingClient cl = it.next() ;
+
+ try {
+ cl.getClient().getStub().stopVM() ;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+
+ cl.getClient().setStatus( "connected" ) ;
+ cl.getClient().setComputingClient( null ) ;
+ it.remove() ;
+ cl = null ;
+ }
+
+ }
+
+
+
+ @Override
+ public String getAssociatedIP( String _ip ) throws RemoteException
+ {
+ String ret = null ;
+
+ for( int i = 0 ; i < vmIPs.size() ; i++ )
+ {
+ if( vmIPs.get( i ).getHostIP().equalsIgnoreCase( _ip ) )
+ {
+ ret = vmIPs.get( i ).getVmIP() ;
+ break ;
+ }
+ }
+
+ return ret ;
+ }
+
+}
+
+/** La programmation est un art, respectons ceux qui la pratiquent !! **/
+