VirtualBox

Changeset 37074 in vbox


Ignore:
Timestamp:
May 13, 2011 2:32:50 PM (14 years ago)
Author:
vboxsync
Message:

Main; VBoxManage: initial machine clone support

Location:
trunk/src/VBox
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r35741 r37074  
    232232#endif /* !VBOX_ONLY_DOCS */
    233233
    234 #ifdef RT_OS_WINDOWS 
     234#ifdef RT_OS_WINDOWS
    235235// Required for ATL
    236236static CComModule _Module;
     
    399399            { "registervm",       USAGE_REGISTERVM,        handleRegisterVM },
    400400            { "unregistervm",     USAGE_UNREGISTERVM,      handleUnregisterVM },
     401            { "clonevm",          USAGE_CLONEVM,           handleCloneVM },
    401402            { "createhd",         USAGE_CREATEHD,          handleCreateHardDisk },
    402403            { "createvdi",        USAGE_CREATEHD,          handleCreateHardDisk }, /* backward compatibility */
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r36067 r37074  
    4545#define USAGE_CREATEVM              RT_BIT_64(4)
    4646#define USAGE_MODIFYVM              RT_BIT_64(5)
    47 #define USAGE_STARTVM               RT_BIT_64(6)
    48 #define USAGE_CONTROLVM             RT_BIT_64(7)
    49 #define USAGE_DISCARDSTATE          RT_BIT_64(8)
    50 #define USAGE_SNAPSHOT              RT_BIT_64(9)
     47#define USAGE_CLONEVM               RT_BIT_64(6)
     48#define USAGE_STARTVM               RT_BIT_64(7)
     49#define USAGE_CONTROLVM             RT_BIT_64(8)
     50#define USAGE_DISCARDSTATE          RT_BIT_64(9)
     51#define USAGE_SNAPSHOT              RT_BIT_64(10)
    5152#define USAGE_CLOSEMEDIUM           RT_BIT_64(11)
    5253#define USAGE_SHOWHDINFO            RT_BIT_64(12)
     
    210211int handleUnregisterVM(HandlerArg *a);
    211212int handleCreateVM(HandlerArg *a);
     213int handleCloneVM(HandlerArg *a);
    212214int handleStartVM(HandlerArg *a);
    213215int handleDiscardState(HandlerArg *a);
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp

    r36720 r37074  
    333333    }
    334334
     335    if (u64Cmd & USAGE_CLONEVM)
     336        RTStrmPrintf(pStrm,
     337                     "VBoxManage clonevm          <uuid>|<name>\n"
     338                     "                            [--name <name>]\n"
     339                     "                            [--basefolder <basefolder>]\n"
     340                     "                            [--uuid <uuid>]\n"
     341                     "                            [--register]\n"
     342                     "\n");
     343
    335344    if (u64Cmd & USAGE_IMPORTAPPLIANCE)
    336345        RTStrmPrintf(pStrm,
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp

    r36673 r37074  
    266266
    267267    return SUCCEEDED(rc) ? 0 : 1;
     268}
     269
     270static const RTGETOPTDEF g_aCloneVMOptions[] =
     271{
     272    { "--name",           'n', RTGETOPT_REQ_STRING },
     273    { "--register",       'r', RTGETOPT_REQ_NOTHING },
     274    { "--basefolder",     'p', RTGETOPT_REQ_STRING },
     275    { "--uuid",           'u', RTGETOPT_REQ_STRING },
     276};
     277
     278int handleCloneVM(HandlerArg *a)
     279{
     280    HRESULT rc;
     281    const char *pszSrcName       = NULL;
     282    const char *pszTrgName       = NULL;
     283    const char *pszTrgBaseFolder = NULL;
     284    bool fRegister               = false;
     285    RTUUID trgUuid;
     286
     287    int c;
     288    RTGETOPTUNION ValueUnion;
     289    RTGETOPTSTATE GetState;
     290    // start at 0 because main() has hacked both the argc and argv given to us
     291    RTGetOptInit(&GetState, a->argc, a->argv, g_aCloneVMOptions, RT_ELEMENTS(g_aCloneVMOptions),
     292                 0, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
     293    while ((c = RTGetOpt(&GetState, &ValueUnion)))
     294    {
     295        switch (c)
     296        {
     297            case 'n':   // --name
     298                pszTrgName = ValueUnion.psz;
     299                break;
     300
     301            case 'p':   // --basefolder
     302                pszTrgBaseFolder = ValueUnion.psz;
     303                break;
     304
     305            case 'u':   // --uuid
     306                if (RT_FAILURE(RTUuidFromStr(&trgUuid, ValueUnion.psz)))
     307                    return errorArgument("Invalid UUID format %s\n", ValueUnion.psz);
     308                break;
     309
     310            case 'r':   // --register
     311                fRegister = true;
     312                break;
     313
     314            case VINF_GETOPT_NOT_OPTION:
     315                if (!pszSrcName)
     316                    pszSrcName = ValueUnion.psz;
     317                else
     318                    return errorSyntax(USAGE_CLONEVM, "Invalid parameter '%s'", ValueUnion.psz);
     319                break;
     320
     321            default:
     322                return errorGetOpt(USAGE_CLONEVM, c, &ValueUnion);
     323        }
     324    }
     325
     326    /* ~heck for required options */
     327    if (!pszSrcName)
     328        return errorSyntax(USAGE_CLONEVM, "VM name required");
     329
     330    ComPtr<IMachine> srcMachine;
     331    CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(pszSrcName).raw(),
     332                                               srcMachine.asOutParam()),
     333                    RTEXITCODE_FAILURE);
     334
     335    /* Default name necessary? */
     336    if (!pszTrgName)
     337        pszTrgName = RTStrAPrintf2("%s Copy", pszSrcName);
     338
     339    Bstr bstrSettingsFile;
     340    CHECK_ERROR_RET(a->virtualBox,
     341                    ComposeMachineFilename(Bstr(pszTrgName).raw(),
     342                                           Bstr(pszTrgBaseFolder).raw(),
     343                                           bstrSettingsFile.asOutParam()),
     344                    RTEXITCODE_FAILURE);
     345
     346    ComPtr<IMachine> trgMachine;
     347    CHECK_ERROR_RET(a->virtualBox, CreateMachine(bstrSettingsFile.raw(),
     348                                                 Bstr(pszTrgName).raw(),
     349                                                 NULL,
     350                                                 Guid(trgUuid).toUtf16().raw(),
     351                                                 FALSE,
     352                                                 trgMachine.asOutParam()),
     353                    RTEXITCODE_FAILURE);
     354    ComPtr<IProgress> progress;
     355    CHECK_ERROR_RET(srcMachine, CloneTo(trgMachine,
     356                                        FALSE,
     357                                        progress.asOutParam()),
     358                    RTEXITCODE_FAILURE);
     359    rc = showProgress(progress);
     360    if (FAILED(rc))
     361    {
     362        com::ProgressErrorInfo ErrInfo(progress);
     363        com::GluePrintErrorInfo(ErrInfo);
     364        return RTEXITCODE_FAILURE;
     365    }
     366
     367    if (fRegister)
     368        CHECK_ERROR_RET(a->virtualBox, RegisterMachine(trgMachine), RTEXITCODE_FAILURE);
     369
     370    Bstr bstrNewName;
     371    CHECK_ERROR_RET(trgMachine, COMGETTER(Name)(bstrNewName.asOutParam()), RTEXITCODE_FAILURE);
     372    RTPrintf("Machine has been successfully cloned as \"%lS\"\n", bstrNewName.raw());
     373
     374    return RTEXITCODE_SUCCESS;
    268375}
    269376
  • trunk/src/VBox/Main/include/MachineImpl.h

    r36991 r37074  
    840840    HRESULT deleteTaskWorker(DeleteTask &task);
    841841
     842    struct CloneVMTask;
     843    static DECLCALLBACK(int) cloneVMThread(RTTHREAD Thread, void *pvUser);
     844    HRESULT cloneVMTaskWorker(CloneVMTask *pTask);
     845
    842846#ifdef VBOX_WITH_GUEST_PROPS
    843847    HRESULT getGuestPropertyFromService(IN_BSTR aName, BSTR *aValue,
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r36991 r37074  
    7272
    7373#include <VBox/com/array.h>
     74#include <VBox/com/list.h>
    7475
    7576#include <VBox/err.h>
     
    60726073}
    60736074
    6074 STDMETHODIMP Machine::CloneTo(IMachine *aTarget, BOOL aFullClone, IProgress **aProgress)
    6075 {
    6076     NOREF(aTarget); NOREF(aFullClone); NOREF(aProgress);
    6077     ReturnComNotImplemented();
     6075struct Machine::CloneVMTask
     6076{
     6077    ComObjPtr<Machine>          pSrcMachine;
     6078    ComObjPtr<Machine>          pTrgMachine;
     6079    ComObjPtr<Progress>         pProgress;
     6080    bool                        fLink;
     6081    typedef struct
     6082    {
     6083        ComPtr<IMedium>         pMedium;
     6084        uint64_t                uSize;
     6085    }MediumTask;
     6086    typedef RTCList<MediumTask> MediumTaskChain;
     6087    RTCList<MediumTaskChain>    llMedias;
     6088};
     6089
     6090STDMETHODIMP Machine::CloneTo(IMachine *pTarget, BOOL fFullClone, IProgress **pProgress)
     6091{
     6092    LogFlowFuncEnter();
     6093
     6094    CheckComArgNotNull(pTarget);
     6095    CheckComArgOutPointerValid(pProgress);
     6096
     6097    AutoCaller autoCaller(this);
     6098    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     6099
     6100    AutoReadLock srcLock(this COMMA_LOCKVAL_SRC_POS);
     6101
     6102    CloneVMTask *pTask = NULL;
     6103
     6104    HRESULT rc;
     6105    try
     6106    {
     6107        pTask = new CloneVMTask;
     6108        pTask->pSrcMachine = this;
     6109        pTask->pTrgMachine = static_cast<Machine*>(pTarget);
     6110        pTask->fLink       = !fFullClone;
     6111
     6112        AutoWriteLock trgLock(pTask->pTrgMachine COMMA_LOCKVAL_SRC_POS);
     6113
     6114        ULONG uCount       = 2; /* One init task and the machine creation. */
     6115        ULONG uTotalWeight = 2; /* The init task and the machine creation is worth one. */
     6116        for (MediaData::AttachmentList::iterator it = mMediaData->mAttachments.begin();
     6117             it != mMediaData->mAttachments.end();
     6118             ++it)
     6119        {
     6120            /* Query some info of the source image. */
     6121            const ComObjPtr<MediumAttachment> &pAtt = *it;
     6122            DeviceType_T type;
     6123            rc = pAtt->COMGETTER(Type)(&type);
     6124            if (FAILED(rc)) throw rc;
     6125
     6126            /* Only harddisk's are of interest. */
     6127            if (type != DeviceType_HardDisk)
     6128                continue;
     6129
     6130            /* Valid medium attached? */
     6131            ComPtr<IMedium> pSrcMedium;
     6132            rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam());
     6133            if (FAILED(rc)) throw rc;
     6134            if (pSrcMedium.isNull())
     6135                continue;
     6136
     6137            /* Build up a child->parent list of this attachment. (Note: we are
     6138             * not interested of any child's not attached to this VM. So this
     6139             * will not create a full copy of the base/child relationship.) */
     6140            Machine::CloneVMTask::MediumTaskChain mtc;
     6141            while(!pSrcMedium.isNull())
     6142            {
     6143                /* Refresh the state so that the file size get read. */
     6144                MediumState_T e;
     6145                rc = pSrcMedium->RefreshState(&e);
     6146                if (FAILED(rc)) throw rc;
     6147                LONG64 lSize;
     6148                rc = pSrcMedium->COMGETTER(Size)(&lSize);
     6149                if (FAILED(rc)) throw rc;
     6150
     6151                /* Save the current medium, for later cloning. */
     6152                Machine::CloneVMTask::MediumTask mt;
     6153                mt.pMedium = pSrcMedium;
     6154                mt.uSize   = lSize;
     6155                mtc.append(mt);
     6156
     6157                /* Calculate progress data */
     6158                ++uCount;
     6159                uTotalWeight += lSize;
     6160
     6161                /* Query next parent. */
     6162                rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam());
     6163                if (FAILED(rc)) throw rc;
     6164            };
     6165            pTask->llMedias.append(mtc);
     6166        }
     6167
     6168        rc = pTask->pProgress.createObject();
     6169        if (FAILED(rc)) throw rc;
     6170        rc = pTask->pProgress->init(getVirtualBox(),
     6171                                    static_cast<IMachine*>(this) /* aInitiator */,
     6172                                    Bstr(tr("Cloning Machine")).raw(),
     6173                                    true /* fCancellable */,
     6174                                    uCount,
     6175                                    uTotalWeight,
     6176                                    Bstr(tr("Initialize Cloning")).raw(),
     6177                                    1);
     6178        if (FAILED(rc)) throw rc;
     6179
     6180        int vrc = RTThreadCreate(NULL,
     6181                                 Machine::cloneVMThread,
     6182                                 static_cast<void*>(pTask),
     6183                                 0,
     6184                                 RTTHREADTYPE_MAIN_WORKER,
     6185                                 0,
     6186                                 "MachineClone");
     6187        if (RT_FAILURE(vrc))
     6188            throw setError(E_FAIL, "Could not create Machine clone thread (%Rrc)", vrc);
     6189    }
     6190    catch (HRESULT rc2)
     6191    {
     6192        if (pTask)
     6193            delete pTask;
     6194        rc = rc2;
     6195    }
     6196
     6197    if (SUCCEEDED(rc))
     6198        pTask->pProgress.queryInterfaceTo(pProgress);
     6199
     6200    LogFlowFuncLeave();
     6201
     6202    return rc;
     6203}
     6204
     6205/**
     6206 * Static task wrapper passed to RTThreadCreate() in Machine::CloneTo() which then
     6207 * calls Machine::cloneVMTaskWorker() on the actual machine object.
     6208 * @param Thread
     6209 * @param pvUser
     6210 * @return
     6211 */
     6212/* static */
     6213DECLCALLBACK(int) Machine::cloneVMThread(RTTHREAD /* Thread */, void *pvUser)
     6214{
     6215    LogFlowFuncEnter();
     6216
     6217    CloneVMTask *pTask = static_cast<CloneVMTask*>(pvUser);
     6218    AssertReturn(pTask,              VERR_INVALID_POINTER);
     6219    AssertReturn(pTask->pSrcMachine, VERR_INVALID_POINTER);
     6220    AssertReturn(pTask->pTrgMachine, VERR_INVALID_POINTER);
     6221    AssertReturn(pTask->pProgress,   VERR_INVALID_POINTER);
     6222
     6223    HRESULT rc = pTask->pSrcMachine->cloneVMTaskWorker(pTask);
     6224    pTask->pProgress->notifyComplete(rc);
     6225
     6226    delete pTask;
     6227
     6228    LogFlowFuncLeave();
     6229
     6230    return VINF_SUCCESS;
     6231}
     6232
     6233/**
     6234 * Task thread implementation for Machine::CloneTo(), called from Machine::cloneVMThread().
     6235 * @param task
     6236 * @return
     6237 */
     6238HRESULT Machine::cloneVMTaskWorker(CloneVMTask *pTask)
     6239{
     6240    AutoCaller autoCaller(this);
     6241    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     6242
     6243    AutoReadLock  srcLock(this COMMA_LOCKVAL_SRC_POS);
     6244    AutoWriteLock trgLock(pTask->pTrgMachine COMMA_LOCKVAL_SRC_POS);
     6245
     6246    HRESULT rc = S_OK;
     6247
     6248    /*
     6249     * Todo:
     6250     * - Regardless where the old media comes from (e.g. snapshots folder) it
     6251     *   goes to the new main VM folder. Maybe we like to be a little bit
     6252     *   smarter here.
     6253     * - Snapshot diffs (can) have the uuid as name. After cloning this isn't
     6254     *   right anymore. Is it worth to change to the new uuid? Or should the
     6255     *   cloned disks called exactly as the original one or should all new disks
     6256     *   get a new name with the new VM name in it.
     6257     */
     6258
     6259    /* Where should all the media go? */
     6260    Utf8Str strTrgMachineFolder = pTask->pTrgMachine->getSettingsFileFull();
     6261    strTrgMachineFolder.stripFilename();
     6262
     6263    RTCList< ComObjPtr<Medium> > newMedias; /* All created images */
     6264    try
     6265    {
     6266        /* Copy all the configuration from this machine to an empty
     6267         * configuration dataset. */
     6268        settings::MachineConfigFile *pTrgMCF = new settings::MachineConfigFile(0);
     6269        *pTrgMCF = *mData->pMachineConfigFile;
     6270
     6271        /* Reset media registry. */
     6272        pTrgMCF->mediaRegistry.llHardDisks.clear();
     6273        /* Reset all snapshots. */
     6274        pTrgMCF->llFirstSnapshot.clear();
     6275        pTrgMCF->uuidCurrentSnapshot.clear();
     6276        pTrgMCF->strStateFile = "";
     6277        /* Force writing of setting file. */
     6278        pTrgMCF->fCurrentStateModified = true;
     6279        /* Set the new name. */
     6280        pTrgMCF->machineUserData.strName = pTask->pTrgMachine->mUserData->s.strName;
     6281        pTrgMCF->uuid = pTask->pTrgMachine->mData->mUuid;
     6282
     6283        for (size_t i = 0; i < pTask->llMedias.size(); ++i)
     6284        {
     6285            const Machine::CloneVMTask::MediumTaskChain &mtc = pTask->llMedias.at(i);
     6286            ComObjPtr<Medium> pNewParent;
     6287            for (size_t a = mtc.size(); a > 0; --a)
     6288            {
     6289                const Machine::CloneVMTask::MediumTask &mt = mtc.at(a - 1);
     6290                ComPtr<IMedium> pMedium = mt.pMedium;
     6291
     6292                Bstr bstrSrcName;
     6293                rc = pMedium->COMGETTER(Name)(bstrSrcName.asOutParam());
     6294                if (FAILED(rc)) throw rc;
     6295
     6296                rc = pTask->pProgress->SetNextOperation(BstrFmt(tr("Cloning Disk '%ls' ..."), bstrSrcName.raw()).raw(), mt.uSize);
     6297                if (FAILED(rc)) throw rc;
     6298
     6299                ComPtr<IMediumFormat> pSrcFormat;
     6300                rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam());
     6301                ULONG uSrcCaps = 0;
     6302                rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps);
     6303                if (FAILED(rc)) throw rc;
     6304
     6305                Bstr bstrSrcFormat     = "VDI";
     6306                MediumVariant_T srcVar = MediumVariant_Standard;
     6307                /* Is the source file based? */
     6308                if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File)
     6309                {
     6310                    /* Yes, just use the source format. Otherwise the defaults
     6311                     * will be used. */
     6312                    rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam());
     6313                    if (FAILED(rc)) throw rc;
     6314                    rc = pMedium->COMGETTER(Variant)(&srcVar);
     6315                    if (FAILED(rc)) throw rc;
     6316                }
     6317
     6318                /* Start creating the clone. */
     6319                ComObjPtr<Medium> pTarget;
     6320                rc = pTarget.createObject();
     6321                if (FAILED(rc)) throw rc;
     6322
     6323                Utf8Str strFile = Utf8StrFmt("%s%c%lS", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, bstrSrcName.raw());
     6324                rc = pTarget->init(mParent,
     6325                                   Utf8Str(bstrSrcFormat),
     6326                                   strFile,
     6327                                   pTask->pTrgMachine->mData->mUuid,  /* media registry */
     6328                                   NULL                               /* llRegistriesThatNeedSaving */);
     6329                if (FAILED(rc)) throw rc;
     6330
     6331                /* Do the disk cloning. */
     6332                ComPtr<IProgress> progress2;
     6333                rc = pMedium->CloneTo(pTarget,
     6334                                      srcVar,
     6335                                      pNewParent,
     6336                                      progress2.asOutParam());
     6337                if (FAILED(rc)) throw rc;
     6338
     6339                /* Wait until the asynchrony process has finished. */
     6340                srcLock.release();
     6341                rc = pTask->pProgress->WaitForAsyncProgressCompletion(progress2);
     6342                srcLock.acquire();
     6343                if (FAILED(rc)) throw rc;
     6344
     6345                /* Check the result of the asynchrony process. */
     6346                LONG iRc;
     6347                rc = progress2->COMGETTER(ResultCode)(&iRc);
     6348                if (FAILED(rc)) throw rc;
     6349                if (FAILED(iRc))
     6350                {
     6351                    /* If the thread of the progress object has an error, then
     6352                     * retrieve the error info from there, or it'll be lost. */
     6353                    ProgressErrorInfo info(progress2);
     6354                    throw setError(iRc, Utf8Str(info.getText()).c_str());
     6355                }
     6356                /* Remember created medias. */
     6357                newMedias.append(pTarget);
     6358                /* This medium becomes the parent of the next medium in the
     6359                 * chain. */
     6360                pNewParent = pTarget;
     6361            }
     6362
     6363            Bstr bstrSrcId;
     6364            rc = mtc.first().pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());
     6365            if (FAILED(rc)) throw rc;
     6366            Bstr bstrTrgId;
     6367            rc = pNewParent->COMGETTER(Id)(bstrTrgId.asOutParam());
     6368            if (FAILED(rc)) throw rc;
     6369            /* We have to patch the configuration, so it contains the new
     6370             * medium uuid instead of the old one. */
     6371            settings::StorageControllersList::iterator it3;
     6372            for (it3 = pTrgMCF->storageMachine.llStorageControllers.begin();
     6373                 it3 != pTrgMCF->storageMachine.llStorageControllers.end();
     6374                 ++it3)
     6375            {
     6376                settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices;
     6377                settings::AttachedDevicesList::iterator it4;
     6378                for (it4 = llAttachments.begin();
     6379                     it4 != llAttachments.end();
     6380                     ++it4)
     6381                {
     6382                    if (   it4->deviceType == DeviceType_HardDisk
     6383                        && it4->uuid == bstrSrcId)
     6384                        it4->uuid = bstrTrgId;
     6385                }
     6386            }
     6387        }
     6388
     6389        {
     6390            rc = pTask->pProgress->SetNextOperation(BstrFmt(tr("Create Machine Clone '%s' ..."), pTrgMCF->machineUserData.strName.c_str()).raw(), 1);
     6391            if (FAILED(rc)) throw rc;
     6392            /* After modifying the new machine config, we can copy the stuff
     6393             * over to the new machine. The machine have to be mutable for
     6394             * this. */
     6395            rc = pTask->pTrgMachine->checkStateDependency(MutableStateDep);
     6396            if (FAILED(rc)) throw rc;
     6397            rc = pTask->pTrgMachine->loadMachineDataFromSettings(*pTrgMCF,
     6398                                                                 &pTask->pTrgMachine->mData->mUuid);
     6399            if (FAILED(rc)) throw rc;
     6400        }
     6401
     6402        /* The medias are created before the machine was there. We have to make
     6403         * sure the new medias know of there new parent or we get in trouble
     6404         * when the media registry is saved for this VM, especially in case of
     6405         * difference image chain's. See VirtualBox::saveMediaRegistry.*/
     6406//        for (size_t i = 0; i < newBaseMedias.size(); ++i)
     6407//        {
     6408//            rc = newBaseMedias.at(i)->addRegistry(pTask->pTrgMachine->mData->mUuid, true /* fRecursive */);
     6409//            if (FAILED(rc)) throw rc;
     6410//        }
     6411
     6412        /* Now save the new configuration to disk. */
     6413        rc = pTask->pTrgMachine->SaveSettings();
     6414        if (FAILED(rc)) throw rc;
     6415    }
     6416    catch(HRESULT rc2)
     6417    {
     6418        rc = rc2;
     6419    }
     6420    catch (...)
     6421    {
     6422        rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
     6423    }
     6424
     6425    /* Cleanup on failure (CANCEL also) */
     6426    if (FAILED(rc))
     6427    {
     6428        /* Delete all already created medias. (Reverse, cause there could be
     6429         * parent->child relations.) */
     6430        for (size_t i = newMedias.size(); i > 0; --i)
     6431        {
     6432            ComObjPtr<Medium> &pMedium = newMedias.at(i - 1);
     6433            AutoCaller mac(pMedium);
     6434            if (FAILED(mac.rc())) return mac.rc();
     6435            AutoReadLock mlock(pMedium COMMA_LOCKVAL_SRC_POS);
     6436            bool fFile = pMedium->isMediumFormatFile();
     6437            Utf8Str strLoc = pMedium->getLocationFull();
     6438            mlock.release();
     6439            /* Close the medium. If this succeed, delete it finally from the
     6440             * disk. */
     6441            HRESULT rc1 = pMedium->close(NULL, mac);
     6442            if (   SUCCEEDED(rc1)
     6443                && fFile)
     6444                RTFileDelete(strLoc.c_str());
     6445        }
     6446        /* Delete the machine folder when not empty. */
     6447        RTDirRemove(strTrgMachineFolder.c_str());
     6448    }
     6449
     6450    return rc;
    60786451}
    60796452
     
    72727645 *    ensure that the media listed as attachments in the config (which have
    72737646 *    been imported from the OVF) receive the correct registry ID.
     7647 *
     7648 * -- During VM cloning.
    72747649 *
    72757650 * @param config Machine settings from XML.
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette