VirtualBox

Changeset 37449 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Jun 14, 2011 4:34:16 PM (13 years ago)
Author:
vboxsync
Message:

Main;VBoxManage: more clone vm work

Location:
trunk/src/VBox/Main
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r37447 r37449  
    35133513  </interface>
    35143514
     3515  <enum
     3516    name="CloneMode" extends="$unknown"
     3517    uuid="A7A159FE-5096-4B8D-8C3C-D033CB0B35A8"
     3518    >
     3519
     3520    <desc>
     3521    Clone mode, used with <link to="IMachine::cloneTo" />.
     3522    </desc>
     3523
     3524    <const name="MachineState"                 value="1">
     3525      <desc>Clone the state of the machine.</desc>
     3526    </const>
     3527    <const name="MachineAndChildStates"        value="2">
     3528      <desc>Clone the state of the machine and if this machine object has child snapshots the state of this childs.</desc>
     3529    </const>
     3530    <const name="AllStates"                    value="3">
     3531      <desc>Clone all states (including all snapshots) of the machine, regardless of the machine object used.</desc>
     3532    </const>
     3533
     3534  </enum>
     3535
    35153536
    35163537  <interface
    35173538    name="IMachine" extends="$unknown"
    3518     uuid="84208466-c072-4e64-b993-c35c096cc837"
     3539    uuid="5A398458-266D-4DCD-9745-0886AEBD761B"
    35193540    wsmap="managed"
    35203541    >
     
    59635984        <desc>Target machine object.</desc>
    59645985      </param>
     5986      <param name="mode" type="CloneMode" dir="in">
     5987        <desc>Which states should be cloned.</desc>
     5988      </param>
    59655989      <param name="fullClone" type="boolean" dir="in">
    59665990        <desc>Selects whether a full or linked clone is created.</desc>
     
    91299153    <method name="waitForAsyncProgressCompletion">
    91309154      <desc>
    9131          Waits until the other task is completed (including all
    9132          sub-operations) and forward all changes from the other progress to
    9133          this progress. This means sub-operation number, description, percent
    9134          and so on.
    9135 
    9136          You have to take care on setting up at least the same count on
    9137          sub-operations in this progress object like there are in the other
    9138          progress object.
    9139 
    9140          If the other progress object supports cancel and this object gets any
    9141          cancel request (when here enabled as well), it will be forwarded to
    9142          the other progress object.
    9143 
    9144          If there is an error in the other progress, this error isn't
    9145          automatically transfered to this progress object. So you have to
    9146          check any operation error within the other progress object, after
    9147          this method returns.
    9148       </desc>
    9149 
    9150      <param name="pProgressAsync" type="IProgress" dir="in">
    9151        <desc>
    9152          The progress object of the asynchrony process.
    9153        </desc>
    9154      </param>
     9155          Waits until the other task is completed (including all
     9156          sub-operations) and forward all changes from the other progress to
     9157          this progress. This means sub-operation number, description, percent
     9158          and so on.
     9159         
     9160          You have to take care on setting up at least the same count on
     9161          sub-operations in this progress object like there are in the other
     9162          progress object.
     9163
     9164          If the other progress object supports cancel and this object gets any
     9165          cancel request (when here enabled as well), it will be forwarded to
     9166          the other progress object.
     9167
     9168          If there is an error in the other progress, this error isn't
     9169          automatically transfered to this progress object. So you have to
     9170          check any operation error within the other progress object, after
     9171          this method returns.
     9172      </desc>
     9173
     9174      <param name="pProgressAsync" type="IProgress" dir="in">
     9175        <desc>
     9176          The progress object of the asynchrony process.
     9177        </desc>
     9178      </param>
    91559179    </method>
    91569180
     
    91789202  <interface
    91799203    name="ISnapshot" extends="$unknown"
    9180     uuid="1a2d0551-58a4-4107-857e-ef414fc42ffc"
     9204    uuid="0472823b-c6e7-472a-8e9f-d732e86b8463"
    91819205    wsmap="managed"
    91829206    >
     
    93259349      </desc>
    93269350    </attribute>
     9351
     9352    <method name="getChildrenCount" const="yes">
     9353      <desc>
     9354        Returns the number of direct childrens of this snapshot.
     9355      </desc>
     9356      <param name="childrenCount" type="unsigned long" dir="return">
     9357        <desc>
     9358        </desc>
     9359      </param>
     9360    </method>
    93279361
    93289362  </interface>
     
    1080510839        medium which is being cloned. Even cloning to a child of the source
    1080610840        medium is possible. Note that when cloning to an existing image, the
    10807         @a parent irgument is ignored.
     10841        @a parent argument is ignored.
    1080810842
    1080910843        After the returned progress object reports that the operation is
  • trunk/src/VBox/Main/include/MachineImpl.h

    r37380 r37449  
    529529    STDMETHOD(AttachHostPciDevice(LONG hostAddress, LONG desiredGuestAddress, BOOL tryToUnbind));
    530530    STDMETHOD(DetachHostPciDevice(LONG hostAddress));
    531     STDMETHOD(CloneTo(IMachine *aTarget, BOOL aFullClone, IProgress **aProgress));
     531    STDMETHOD(CloneTo(IMachine *aTarget, CloneMode_T mode, BOOL aFullClone, IProgress **aProgress));
    532532    // public methods only for internal purposes
    533533
     
    841841
    842842    struct CloneVMTask;
     843    HRESULT cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComPtr<IMachine> > &machineList) const;
     844    settings::Snapshot cloneFindSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const;
     845    void cloneUpdateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
     846    void cloneUpdateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
     847
    843848    static DECLCALLBACK(int) cloneVMThread(RTTHREAD Thread, void *pvUser);
    844849    HRESULT cloneVMTaskWorker(CloneVMTask *pTask);
  • trunk/src/VBox/Main/include/SnapshotImpl.h

    r36074 r37449  
    8383
    8484    // ISnapshot methods
     85    STDMETHOD(GetChildrenCount)(ULONG* count);
    8586
    8687    // public methods only for internal purposes
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r37412 r37449  
    60776077    ComObjPtr<Machine>          pSrcMachine;
    60786078    ComObjPtr<Machine>          pTrgMachine;
     6079    ComPtr<IMachine>            pOldMachineState;
    60796080    ComObjPtr<Progress>         pProgress;
    6080     bool                        fLink;
     6081    Guid                        snapshotId;
     6082    CloneMode_T                 mode;
     6083    bool                        fLinkDisks;
    60816084    typedef struct
    60826085    {
     
    60846087        uint64_t                uSize;
    60856088    }MediumTask;
    6086     typedef RTCList<MediumTask> MediumTaskChain;
     6089    typedef struct
     6090    {
     6091        RTCList<MediumTask>     chain;
     6092        bool                    fCreateDiffs;
     6093    }MediumTaskChain;
    60876094    RTCList<MediumTaskChain>    llMedias;
     6095    RTCList< std::pair<Utf8Str, Utf8Str> > llSaveStateFiles; /* Snapshot UUID -> File path */
    60886096};
    60896097
    6090 STDMETHODIMP Machine::CloneTo(IMachine *pTarget, BOOL fFullClone, IProgress **pProgress)
     6098STDMETHODIMP Machine::CloneTo(IMachine *pTarget, CloneMode_T mode, BOOL fFullClone, IProgress **pProgress)
    60916099{
    60926100    LogFlowFuncEnter();
     
    61066114    {
    61076115        pTask = new CloneVMTask;
    6108         pTask->pSrcMachine = this;
    6109         pTask->pTrgMachine = static_cast<Machine*>(pTarget);
    6110         pTask->fLink       = !fFullClone;
    6111 
     6116        pTask->pSrcMachine   = this;
     6117        pTask->pTrgMachine   = static_cast<Machine*>(pTarget);
     6118        pTask->fLinkDisks    = !fFullClone;
     6119        pTask->mode          = mode;
     6120
     6121        /* Lock the target machine early (so nobody mess around with it in the meantime). */
    61126122        AutoWriteLock trgLock(pTask->pTrgMachine COMMA_LOCKVAL_SRC_POS);
    61136123
     6124        if (pTask->pSrcMachine->isSnapshotMachine())
     6125            pTask->snapshotId  = static_cast<SnapshotMachine*>((Machine*)pTask->pSrcMachine)->getSnapshotId();
     6126
     6127        /* Add the current machine and all snapshot machines below this machine
     6128         * in a list for further processing. */
     6129        RTCList< ComPtr<IMachine> > machineList;
     6130
     6131        /* Include current state? */
     6132        if (   pTask->mode == CloneMode_MachineState
     6133            || pTask->mode == CloneMode_AllStates)
     6134            machineList.append(static_cast< ComPtr<IMachine> >(pTask->pSrcMachine));
     6135        /* Should be done a depth copy with all child snapshots? */
     6136        if (   pTask->mode == CloneMode_MachineAndChildStates
     6137            || pTask->mode == CloneMode_AllStates)
     6138        {
     6139            ULONG cSnapshots = 0;
     6140            rc = pTask->pSrcMachine->COMGETTER(SnapshotCount)(&cSnapshots);
     6141            if (FAILED(rc)) throw rc;
     6142            if (cSnapshots > 0)
     6143            {
     6144                Utf8Str id;
     6145                if (   pTask->mode == CloneMode_MachineAndChildStates
     6146                    && !pTask->snapshotId.isEmpty())
     6147                    id = pTask->snapshotId.toString();
     6148                ComPtr<ISnapshot> pSnapshot;
     6149                rc = pTask->pSrcMachine->FindSnapshot(Bstr(id).raw(), pSnapshot.asOutParam());
     6150                if (FAILED(rc)) throw rc;
     6151                rc = cloneCreateMachineList(pSnapshot, machineList);
     6152                if (FAILED(rc)) throw rc;
     6153                rc = pSnapshot->COMGETTER(Machine)(pTask->pOldMachineState.asOutParam());
     6154                if (FAILED(rc)) throw rc;
     6155            }
     6156        }
     6157
     6158        /* Go over every machine and walk over every attachment this machine has. */
    61146159        ULONG uCount       = 2; /* One init task and the machine creation. */
    61156160        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);
     6161        for (size_t i = 0; i < machineList.size(); ++i)
     6162        {
     6163            /* If this is the Snapshot Machine we want to clone, we need to
     6164             * create a new diff file for the new "current state". */
     6165            bool fCreateDiffs = false;
     6166            if (machineList.at(i) == pTask->pOldMachineState)
     6167                fCreateDiffs = true;
     6168            SafeIfaceArray<IMediumAttachment> sfaAttachments;
     6169            rc = machineList.at(i)->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
    61246170            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())
     6171            /* Add all attachments (and there parents) of the different
     6172             * machines to a worker list. */
     6173            for (size_t a = 0; a < sfaAttachments.size(); ++a)
    61426174            {
    6143                 /* Refresh the state so that the file size get read. */
    6144                 MediumState_T e;
    6145                 rc = pSrcMedium->RefreshState(&e);
     6175                const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a];
     6176                DeviceType_T type;
     6177                rc = pAtt->COMGETTER(Type)(&type);
    61466178                if (FAILED(rc)) throw rc;
    6147                 LONG64 lSize;
    6148                 rc = pSrcMedium->COMGETTER(Size)(&lSize);
     6179
     6180                /* Only harddisk's are of interest. */
     6181                if (type != DeviceType_HardDisk)
     6182                    continue;
     6183
     6184                /* Valid medium attached? */
     6185                ComPtr<IMedium> pSrcMedium;
     6186                rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam());
    61496187                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);
     6188                if (pSrcMedium.isNull())
     6189                    continue;
     6190
     6191                /* Build up a child->parent list of this attachment. (Note: we are
     6192                 * not interested of any child's not attached to this VM. So this
     6193                 * will not create a full copy of the base/child relationship.) */
     6194                Machine::CloneVMTask::MediumTaskChain mtc;
     6195                mtc.fCreateDiffs = fCreateDiffs;
     6196                while(!pSrcMedium.isNull())
     6197                {
     6198                    /* Refresh the state so that the file size get read. */
     6199                    MediumState_T e;
     6200                    rc = pSrcMedium->RefreshState(&e);
     6201                    if (FAILED(rc)) throw rc;
     6202                    LONG64 lSize;
     6203                    rc = pSrcMedium->COMGETTER(Size)(&lSize);
     6204                    if (FAILED(rc)) throw rc;
     6205
     6206                    /* Save the current medium, for later cloning. */
     6207                    Machine::CloneVMTask::MediumTask mt;
     6208                    mt.pMedium = pSrcMedium;
     6209                    mt.uSize   = lSize;
     6210                    mtc.chain.append(mt);
     6211
     6212                    /* Calculate progress data */
     6213                    ++uCount;
     6214                    uTotalWeight += lSize;
     6215
     6216                    /* Query next parent. */
     6217                    rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam());
     6218                    if (FAILED(rc)) throw rc;
     6219                };
     6220                pTask->llMedias.append(mtc);
     6221            }
     6222            /* Todo: If this machine has save state files, they have to be copied as well. */
     6223//            Bstr bstrSrcSaveStatePath;
     6224//            rc = machineList.at(i)->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam());
     6225//            if (FAILED(rc)) throw rc;
     6226//            if (!bstrSrcSaveStatePath.isEmpty())
     6227//                pTask->llSaveStates.append(bstrSrcSaveStatePath);
    61666228        }
    61676229
     
    62316293}
    62326294
     6295HRESULT Machine::cloneCreateMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComPtr<IMachine> > &machineList) const
     6296{
     6297    HRESULT rc = S_OK;
     6298    Bstr name;
     6299    rc = pSnapshot->COMGETTER(Name)(name.asOutParam());
     6300    if (FAILED(rc)) return rc;
     6301
     6302    ComPtr<IMachine> pMachine;
     6303    rc = pSnapshot->COMGETTER(Machine)(pMachine.asOutParam());
     6304    if (FAILED(rc)) return rc;
     6305    machineList.append(pMachine);
     6306
     6307    SafeIfaceArray<ISnapshot> sfaChilds;
     6308    rc = pSnapshot->COMGETTER(Children)(ComSafeArrayAsOutParam(sfaChilds));
     6309    if (FAILED(rc)) return rc;
     6310    for (size_t i = 0; i < sfaChilds.size(); ++i)
     6311    {
     6312        rc = cloneCreateMachineList(sfaChilds[i], machineList);
     6313        if (FAILED(rc)) return rc;
     6314    }
     6315
     6316    return rc;
     6317}
     6318
     6319settings::Snapshot Machine::cloneFindSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const
     6320{
     6321    settings::SnapshotsList::const_iterator it;
     6322    for (it = snl.begin(); it != snl.end(); ++it)
     6323    {
     6324        if (it->uuid == id)
     6325            return *it;
     6326        else if (!it->llChildSnapshots.empty())
     6327            return cloneFindSnapshot(pMCF, it->llChildSnapshots, id);
     6328    }
     6329    return settings::Snapshot();
     6330}
     6331
     6332void Machine::cloneUpdateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const
     6333{
     6334    settings::StorageControllersList::iterator it3;
     6335    for (it3 = sc.begin();
     6336         it3 != sc.end();
     6337         ++it3)
     6338    {
     6339        settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices;
     6340        settings::AttachedDevicesList::iterator it4;
     6341        for (it4 = llAttachments.begin();
     6342             it4 != llAttachments.end();
     6343             ++it4)
     6344        {
     6345            if (   it4->deviceType == DeviceType_HardDisk
     6346                && it4->uuid == bstrOldId)
     6347            {
     6348                it4->uuid = bstrNewId;
     6349            }
     6350        }
     6351    }
     6352}
     6353
     6354void Machine::cloneUpdateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const
     6355{
     6356    settings::SnapshotsList::iterator it;
     6357    for (  it  = sl.begin();
     6358           it != sl.end();
     6359         ++it)
     6360    {
     6361        cloneUpdateStorageLists(it->storage.llStorageControllers, bstrOldId, bstrNewId);
     6362        if (!it->llChildSnapshots.empty())
     6363            cloneUpdateSnapshotStorageLists(it->llChildSnapshots, bstrOldId, bstrNewId);
     6364    }
     6365}
     6366
    62336367/**
    62346368 * Task thread implementation for Machine::CloneTo(), called from Machine::cloneVMThread().
     
    62716405        /* Reset media registry. */
    62726406        pTrgMCF->mediaRegistry.llHardDisks.clear();
    6273         /* Reset all snapshots. */
    6274         pTrgMCF->llFirstSnapshot.clear();
    6275         pTrgMCF->uuidCurrentSnapshot.clear();
     6407        /* If we got a valid snapshot id, replace the hardware/storage section
     6408         * with the stuff from the snapshot. */
     6409        settings::Snapshot sn;
     6410        if (!pTask->snapshotId.isEmpty())
     6411            sn = cloneFindSnapshot(pTrgMCF, pTrgMCF->llFirstSnapshot, pTask->snapshotId);
     6412
     6413        if (pTask->mode == CloneMode_MachineState)
     6414        {
     6415            if (!sn.uuid.isEmpty())
     6416            {
     6417                pTrgMCF->hardwareMachine = sn.hardware;
     6418                pTrgMCF->storageMachine  = sn.storage;
     6419            }
     6420
     6421            /* Remove any hint on snapshots. */
     6422            pTrgMCF->llFirstSnapshot.clear();
     6423            pTrgMCF->uuidCurrentSnapshot.clear();
     6424        }else
     6425        if (   pTask->mode == CloneMode_MachineAndChildStates
     6426            && !sn.uuid.isEmpty())
     6427        {
     6428            /* Copy the snapshot data to the current machine. */
     6429            pTrgMCF->hardwareMachine = sn.hardware;
     6430            pTrgMCF->storageMachine  = sn.storage;
     6431
     6432            /* The snapshot will be the root one. */
     6433            pTrgMCF->uuidCurrentSnapshot = sn.uuid;
     6434            pTrgMCF->llFirstSnapshot.clear();
     6435            pTrgMCF->llFirstSnapshot.push_back(sn);
     6436        }
     6437
     6438        /* Reset the snapshot folder to 'Snapshots' within the target directory.
     6439         * Todo: Not sure if this is what we want. */
     6440        pTrgMCF->machineUserData.strSnapshotFolder = "Snapshots";
    62766441        pTrgMCF->strStateFile = "";
    62776442        /* Force writing of setting file. */
     
    62816446        pTrgMCF->uuid = pTask->pTrgMachine->mData->mUuid;
    62826447
     6448        /* The absolute name of the snapshot folder. */
     6449        Utf8Str strTrgSnapshotFolder = Utf8StrFmt("%s%c%s%c", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, pTrgMCF->machineUserData.strSnapshotFolder.c_str(), RTPATH_DELIMITER);
     6450
     6451        /* We need to create a map with the already created medias. This is
     6452         * necessary, cause different snapshots could have the same
     6453         * parents/parent chain. If a medium is in this map already, it isn't
     6454         * cloned a second time, but simply used. */
     6455        typedef std::map<Utf8Str, ComObjPtr<Medium> > TStrMediumMap;
     6456        typedef std::pair<Utf8Str, ComObjPtr<Medium> > TStrMediumPair;
     6457        TStrMediumMap map;
    62836458        for (size_t i = 0; i < pTask->llMedias.size(); ++i)
    62846459        {
    62856460            const Machine::CloneVMTask::MediumTaskChain &mtc = pTask->llMedias.at(i);
    62866461            ComObjPtr<Medium> pNewParent;
    6287             for (size_t a = mtc.size(); a > 0; --a)
     6462            for (size_t a = mtc.chain.size(); a > 0; --a)
    62886463            {
    6289                 const Machine::CloneVMTask::MediumTask &mt = mtc.at(a - 1);
     6464                const Machine::CloneVMTask::MediumTask &mt = mtc.chain.at(a - 1);
    62906465                ComPtr<IMedium> pMedium = mt.pMedium;
    62916466
     
    62976472                if (FAILED(rc)) throw rc;
    62986473
    6299                 ComPtr<IMediumFormat> pSrcFormat;
    6300                 rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam());
    6301                 ULONG uSrcCaps = 0;
    6302                 rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps);
     6474                Bstr bstrSrcId;
     6475                rc = pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());
    63036476                if (FAILED(rc)) throw rc;
    63046477
    6305                 Bstr bstrSrcFormat     = "VDI";
    6306                 ULONG srcVar = MediumVariant_Standard;
    6307                 /* Is the source file based? */
    6308                 if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File)
     6478                /* Is a clone already there? */
     6479                TStrMediumMap::iterator it = map.find(Utf8Str(bstrSrcId));
     6480                if (it != map.end())
     6481                    pNewParent = it->second;
     6482                else
    63096483                {
    6310                     /* Yes, just use the source format. Otherwise the defaults
    6311                      * will be used. */
    6312                     rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam());
     6484                    ComPtr<IMediumFormat> pSrcFormat;
     6485                    rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam());
     6486                    ULONG uSrcCaps = 0;
     6487                    rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps);
    63136488                    if (FAILED(rc)) throw rc;
    6314                     rc = pMedium->COMGETTER(Variant)(&srcVar);
     6489
     6490                    Bstr bstrSrcFormat = "VDI";
     6491                    ULONG srcVar = MediumVariant_Standard;
     6492                    /* Is the source file based? */
     6493                    if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File)
     6494                    {
     6495                        /* Yes, just use the source format. Otherwise the defaults
     6496                         * will be used. */
     6497                        rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam());
     6498                        if (FAILED(rc)) throw rc;
     6499                        rc = pMedium->COMGETTER(Variant)(&srcVar);
     6500                        if (FAILED(rc)) throw rc;
     6501                    }
     6502
     6503                    /* Start creating the clone. */
     6504                    ComObjPtr<Medium> pTarget;
     6505                    rc = pTarget.createObject();
    63156506                    if (FAILED(rc)) throw rc;
     6507
     6508                    Utf8Str strFile = Utf8StrFmt("%s%c%lS", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, bstrSrcName.raw());
     6509                    rc = pTarget->init(mParent,
     6510                                       Utf8Str(bstrSrcFormat),
     6511                                       strFile,
     6512                                       pTask->pTrgMachine->mData->mUuid,  /* media registry */
     6513                                       NULL                               /* llRegistriesThatNeedSaving */);
     6514                    if (FAILED(rc)) throw rc;
     6515
     6516                    /* Do the disk cloning. */
     6517                    ComPtr<IProgress> progress2;
     6518                    rc = pMedium->CloneTo(pTarget,
     6519                                          srcVar,
     6520                                          pNewParent,
     6521                                          progress2.asOutParam());
     6522                    if (FAILED(rc)) throw rc;
     6523
     6524                    /* Wait until the asynchrony process has finished. */
     6525                    srcLock.release();
     6526                    rc = pTask->pProgress->WaitForAsyncProgressCompletion(progress2);
     6527                    srcLock.acquire();
     6528                    if (FAILED(rc)) throw rc;
     6529
     6530                    /* Check the result of the asynchrony process. */
     6531                    LONG iRc;
     6532                    rc = progress2->COMGETTER(ResultCode)(&iRc);
     6533                    if (FAILED(rc)) throw rc;
     6534                    if (FAILED(iRc))
     6535                    {
     6536                        /* If the thread of the progress object has an error, then
     6537                         * retrieve the error info from there, or it'll be lost. */
     6538                        ProgressErrorInfo info(progress2);
     6539                        throw setError(iRc, Utf8Str(info.getText()).c_str());
     6540                    }
     6541
     6542                    map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pTarget));
     6543
     6544                    /* Remember created medias. */
     6545                    newMedias.append(pTarget);
     6546                    /* This medium becomes the parent of the next medium in the
     6547                     * chain. */
     6548                    pNewParent = pTarget;
    63166549                }
    6317 
    6318                 /* Start creating the clone. */
    6319                 ComObjPtr<Medium> pTarget;
    6320                 rc = pTarget.createObject();
     6550            }
     6551
     6552            /* Create diffs for the last image chain. */
     6553            if (mtc.fCreateDiffs)
     6554            {
     6555                Bstr bstrSrcId;
     6556                rc = pNewParent->COMGETTER(Id)(bstrSrcId.asOutParam());
    63216557                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 */);
     6558                GuidList *pllRegistriesThatNeedSaving;
     6559                ComObjPtr<Medium> diff;
     6560                diff.createObject();
     6561                rc = diff->init(mParent,
     6562                                pNewParent->getPreferredDiffFormat(),
     6563                                strTrgSnapshotFolder,
     6564                                pTask->pTrgMachine->mData->mUuid,
     6565                                NULL); // pllRegistriesThatNeedSaving
    63296566                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());
     6567                MediumLockList *pMediumLockList(new MediumLockList()); /* todo: deleteeeeeeeee */
     6568                rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
     6569                                                true /* fMediumLockWrite */,
     6570                                                pNewParent,
     6571                                                *pMediumLockList);
    63376572                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();
     6573                rc = pMediumLockList->Lock();
    63436574                if (FAILED(rc)) throw rc;
    6344 
    6345                 /* Check the result of the asynchrony process. */
    6346                 LONG iRc;
    6347                 rc = progress2->COMGETTER(ResultCode)(&iRc);
     6575                rc = pNewParent->createDiffStorage(diff, MediumVariant_Standard,
     6576                                                   pMediumLockList,
     6577                                                   NULL /* aProgress */,
     6578                                                   true /* aWait */,
     6579                                                   NULL); // pllRegistriesThatNeedSaving
     6580                delete pMediumLockList;
    63486581                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;
     6582                pNewParent = diff;
    63616583            }
    6362 
    63636584            Bstr bstrSrcId;
    6364             rc = mtc.first().pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());
     6585            rc = mtc.chain.first().pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());
    63656586            if (FAILED(rc)) throw rc;
    63666587            Bstr bstrTrgId;
     
    63696590            /* We have to patch the configuration, so it contains the new
    63706591             * 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)
     6592            cloneUpdateStorageLists(pTrgMCF->storageMachine.llStorageControllers, bstrSrcId, bstrTrgId);
     6593            cloneUpdateSnapshotStorageLists(pTrgMCF->llFirstSnapshot, bstrSrcId, bstrTrgId);
     6594        }
     6595        /* Todo: Clone all save state files. */
     6596//        for (size_t i = 0; i < pTask->llSaveStates.size(); ++i)
     6597//        {
     6598//            RTPrintf("save state: %s\n", pTask->llSaveStates.at(i).c_str());
     6599//            RTFileCopy(llSaveStates.at(i).c_str(),);
     6600//        }
     6601
     6602        if (false)
     6603//        if (!pTask->pOldMachineState.isNull())
     6604        {
     6605            SafeIfaceArray<IMediumAttachment> sfaAttachments;
     6606            rc = pTask->pOldMachineState->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
     6607            if (FAILED(rc)) throw rc;
     6608            for (size_t a = 0; a < sfaAttachments.size(); ++a)
    63756609            {
    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                 }
     6610                const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a];
     6611                DeviceType_T type;
     6612                rc = pAtt->COMGETTER(Type)(&type);
     6613                if (FAILED(rc)) throw rc;
     6614
     6615                /* Only harddisk's are of interest. */
     6616                if (type != DeviceType_HardDisk)
     6617                    continue;
     6618
     6619                /* Valid medium attached? */
     6620                ComPtr<IMedium> pSrcMedium;
     6621                rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam());
     6622                if (FAILED(rc)) throw rc;
     6623                if (pSrcMedium.isNull())
     6624                    continue;
     6625
     6626//                ComObjPtr<Medium> pMedium = static_cast<Medium*>((IMedium*)pSrcMedium);
     6627//                ComObjPtr<Medium> diff;
     6628//                diff.createObject();
     6629                // store this diff in the same registry as the parent
     6630//                Guid uuidRegistryParent;
     6631//                if (!medium->getFirstRegistryMachineId(uuidRegistryParent))
     6632//                {
     6633                    // parent image has no registry: this can happen if we're attaching a new immutable
     6634                    // image that has not yet been attached (medium then points to the base and we're
     6635                    // creating the diff image for the immutable, and the parent is not yet registered);
     6636                    // put the parent in the machine registry then
     6637//                    addMediumToRegistry(medium, llRegistriesThatNeedSaving, &uuidRegistryParent);
     6638//                }
     6639//                rc = diff->init(mParent,
     6640//                                pMedium->getPreferredDiffFormat(),
     6641//                                strFullSnapshotFolder.append(RTPATH_SLASH_STR),
     6642//                                uuidRegistryParent,
     6643//                                pllRegistriesThatNeedSaving);
     6644//                if (FAILED(rc)) throw rc;
     6645//
     6646//                rc = pMedium->createDiffStorage(diff, MediumVariant_Standard,
     6647//                                                pMediumLockList,
     6648//                                                NULL /* aProgress */,
     6649//                                                true /* aWait */,
     6650//                                                pllRegistriesThatNeedSaving);
    63866651            }
    63876652        }
  • trunk/src/VBox/Main/src-server/SnapshotImpl.cpp

    r37380 r37449  
    446446    SafeIfaceArray<ISnapshot> collection(m->llChildren);
    447447    collection.detachTo(ComSafeArrayOutArg(aChildren));
     448
     449    return S_OK;
     450}
     451
     452STDMETHODIMP Snapshot::GetChildrenCount(ULONG* count)
     453{
     454    CheckComArgOutPointerValid(count);
     455
     456    *count = getChildrenCount();
    448457
    449458    return S_OK;
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