ConsoleImpl-LiveMigration.cpp revision a95372cb717b804278016fd0a0d4038a40653096
/* $Id$ */
/** @file
* VBox Console COM Class implementation, The Live Migration Part.
*/
/*
* Copyright (C) 2009 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "ConsoleImpl.h"
#include "Logging.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Argument package for Console::migrationServeConnection.
*/
typedef struct MIGRATIONSTATE
{
const char *pszPassword;
void *pvVMCallbackTask;
int rc;
typedef MIGRATIONSTATE *PMIGRATIONSTATE;
/*******************************************************************************
* Global Variables *
*******************************************************************************/
static const char g_szWelcome[] = "VirtualBox-LiveMigration-1.0\n";
/**
* @copydoc SSMSTRMOPS::pfnWrite
*/
static DECLCALLBACK(int) migrationTcpOpWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite)
{
if (RT_SUCCESS(rc))
{
return VINF_SUCCESS;
}
return rc;
}
/**
* @copydoc SSMSTRMOPS::pfnRead
*/
static DECLCALLBACK(int) migrationTcpOpRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead)
{
if (RT_SUCCESS(rc))
{
return VINF_SUCCESS;
}
return rc;
}
/**
* @copydoc SSMSTRMOPS::pfnSeek
*/
static DECLCALLBACK(int) migrationTcpOpSeek(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
{
return VERR_NOT_SUPPORTED;
}
/**
* @copydoc SSMSTRMOPS::pfnTell
*/
{
}
/**
* @copydoc SSMSTRMOPS::pfnSize
*/
{
return VERR_NOT_SUPPORTED;
}
/**
* @copydoc SSMSTRMOPS::pfnClose
*/
{
return VINF_SUCCESS;
}
/**
* Method table for a TCP based stream.
*/
static SSMSTRMOPS const g_migrationTcpOps =
{
};
/**
* @copydoc FNRTTIMERLR
*/
{
/* This is harmless for any open connections. */
}
/**
* Start live migration to the specified target.
*
* @returns COM status code.
*
* @param aHostname The name of the target host.
* @param aPort The TCP port number.
* @param aPassword The password.
* @param aProgress Where to return the progress object.
*/
{
/*
* Validate parameters.
*/
/*
* Try change the state, create a progress object and spawn a worker thread.
*/
return E_FAIL;
}
/**
* Creates a TCP server that listens for the source machine and passes control
* over to Console::migrationServeConnection().
*
* @returns VBox status code.
* @param pVM The VM handle
* @param pMachine The IMachine for the virtual machine.
* @param pvVMCallbackTask The callback task pointer for
* stateProgressCallback().
*/
int
{
/*
* Get the config.
*/
return VERR_GENERAL_FAILURE;
return VERR_GENERAL_FAILURE;
/** @todo Add a bind address property. */
/*
* Create the TCP server.
*/
int rc;
if (uPort)
else
{
{
if (rc != VERR_NET_ADDRESS_IN_USE)
break;
}
if (RT_SUCCESS(rc))
{
{
return VERR_GENERAL_FAILURE;
}
}
}
if (RT_FAILURE(rc))
return rc;
/*
* Create a one-shot timer for timing out after 5 mins.
*/
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/*
* Do the job, when it returns we're done.
*/
if (rc == VERR_TCP_SERVER_STOP)
if (RT_FAILURE(rc))
}
}
return rc;
}
/**
* Reads a string from the socket.
*
* @returns VBox status code.
*
* @param Sock The socket.
* @param pszBuf The output buffer.
* @param cchBuf The size of the output buffer.
*
*/
{
/* dead simple (stupid) approach. */
for (;;)
{
char ch;
if (RT_FAILURE(rc))
{
return rc;
}
if ( ch == '\n'
|| ch == '\0')
return VINF_SUCCESS;
if (cchBuf <= 1)
{
return VERR_BUFFER_OVERFLOW;
}
*pszBuf = '\0';
cchBuf--;
}
}
/**
* @copydoc FNRTTCPSERVE
* VERR_TCP_SERVER_STOP
*/
/*static*/ DECLCALLBACK(int)
{
/*
* Say hello.
*/
if (RT_FAILURE(rc))
{
return VINF_SUCCESS;
}
/*
* Password (includes '\n', see migrationLoadRemote). If it's right, tell
* the TCP server to stop listening (frees up host resources and makes sure
* this is the last connection attempt).
*/
unsigned off = 0;
while (pszPassword[off])
{
char ch;
if (RT_FAILURE(rc))
break;
{
return VINF_SUCCESS;
}
off++;
}
/*
* Command processing loop.
*/
for (;;)
{
char szCmd[128];
if (RT_FAILURE(rc))
break;
{
if (RT_FAILURE(rc))
{
break;
}
}
/** @todo implement config verification and hardware compatability checks. Or
* maybe leave part of these to the saved state machinery? */
break;
else
{
break;
}
}
return VERR_TCP_SERVER_STOP;
}