MachineImplCloneVM.cpp revision d1bb48754376874c3cc6b1091a6abec549663c0c
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Implementation of MachineCloneVM
df2a53dee17325742e7464e7f53d3f99dc500f3avboxsync * Copyright (C) 2011-2013 Oracle Corporation
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * available from http://www.virtualbox.org. This file is free software;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * you can redistribute it and/or modify it under the terms of the GNU
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * General Public License (GPL) as published by the Free Software
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/////////////////////////////////////////////////////////////////////////////
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsynctypedef struct
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsynctypedef struct
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsynctypedef struct
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync// The private class
80e46f984efd827517661c0e081a36014ca41af8vboxsync/////////////////////////////////////////////////////////////////////////////
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync MachineCloneVMPrivate(MachineCloneVM *a_q, ComObjPtr<Machine> &a_pSrcMachine, ComObjPtr<Machine> &a_pTrgMachine, CloneMode_T a_mode, const RTCList<CloneOptions_T> &opts)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Thread management */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync static_cast<void*>(this),
80e46f984efd827517661c0e081a36014ca41af8vboxsync "MachineClone");
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync static int workerThread(RTTHREAD /* Thread */, void *pvUser)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync MachineCloneVMPrivate *pTask = static_cast<MachineCloneVMPrivate*>(pvUser);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Private helper methods */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* MachineCloneVM::start helper: */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync HRESULT createMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComObjPtr<Machine> > &machineList) const;
48dafba24ef28f07a241e5857a43b327822574a8vboxsync inline void updateProgressStats(MEDIUMTASKCHAIN &mtc, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) const;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync inline HRESULT addSaveState(const ComObjPtr<Machine> &machine, ULONG &uCount, ULONG &uTotalWeight);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync inline HRESULT queryBaseName(const ComPtr<IMedium> &pMedium, Utf8Str &strBaseName) const;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync HRESULT queryMediasForMachineState(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync HRESULT queryMediasForMachineAndChildStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync HRESULT queryMediasForAllStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight);
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync /* MachineCloneVM::run helper: */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync bool findSnapshot(const settings::SnapshotsList &snl, const Guid &id, settings::Snapshot &sn) const;
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync void updateMACAddresses(settings::NetworkAdaptersList &nwl) const;
fb1975a6972d89de9e515bed0248db93f04ec9d8vboxsync void updateMACAddresses(settings::SnapshotsList &sl) const;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync void updateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync void updateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync void updateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync HRESULT createDifferencingMedium(const ComObjPtr<Machine> &pMachine, const ComObjPtr<Medium> &pParent, const Utf8Str &strSnapshotFolder, RTCList<ComObjPtr<Medium> > &newMedia, ComObjPtr<Medium> *ppDiff) const;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync static int copyStateFileProgress(unsigned uPercentage, void *pvUser);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Private q and parent pointer */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Private helper members */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync RTCList<SAVESTATETASK> llSaveStateFiles; /* Snapshot UUID -> File path */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncHRESULT MachineCloneVMPrivate::createMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComObjPtr<Machine> > &machineList) const
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pSnapshot->COMGETTER(Name)(name.asOutParam());
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync rc = pSnapshot->COMGETTER(Machine)(pMachine.asOutParam());
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pSnapshot->COMGETTER(Children)(ComSafeArrayAsOutParam(sfaChilds));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncvoid MachineCloneVMPrivate::updateProgressStats(MEDIUMTASKCHAIN &mtc, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight) const
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Implicit diff creation as part of attach is a pretty cheap
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * operation, and does only need one operation per attachment. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Currently the copying of diff images involves reading at least
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * the biggest parent in the previous chain. So even if the new
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * diff image is small in size, it could need some time to create
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * it. Adding the biggest size in the chain should balance this a
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * little bit more, i.e. the weight is the sum of the data which
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * needs to be read and written. */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync /* Calculate progress data */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* Save the max size for better weighting of diff image
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * creation. */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsyncHRESULT MachineCloneVMPrivate::addSaveState(const ComObjPtr<Machine> &machine, ULONG &uCount, ULONG &uTotalWeight)
6febf3149010855617e4a37e2c49f93d68930d44vboxsync HRESULT rc = machine->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam());
63b785c3291332a86a9bc473e68f08121368898bvboxsync int vrc = RTFileQuerySize(sst.strSaveStateFile.c_str(), &cbSize);
63b785c3291332a86a9bc473e68f08121368898bvboxsync return p->setError(VBOX_E_IPRT_ERROR, p->tr("Could not query file size of '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), vrc);
63b785c3291332a86a9bc473e68f08121368898bvboxsync /* same rule as above: count both the data which needs to
63b785c3291332a86a9bc473e68f08121368898bvboxsync * be read and written */
63b785c3291332a86a9bc473e68f08121368898bvboxsync sst.uWeight = (ULONG)(2 * (cbSize + _1M - 1) / _1M);
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsyncHRESULT MachineCloneVMPrivate::queryBaseName(const ComPtr<IMedium> &pMedium, Utf8Str &strBaseName) const
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync HRESULT rc = pMedium->COMGETTER(Base)(pBaseMedium.asOutParam());
80e46f984efd827517661c0e081a36014ca41af8vboxsync rc = pBaseMedium->COMGETTER(Name)(bstrBaseName.asOutParam());
80e46f984efd827517661c0e081a36014ca41af8vboxsyncHRESULT MachineCloneVMPrivate::queryMediasForMachineState(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight)
80e46f984efd827517661c0e081a36014ca41af8vboxsync /* This mode is pretty straightforward. We didn't need to know about any
80e46f984efd827517661c0e081a36014ca41af8vboxsync * parent/children relationship and therefor simply adding all directly
80e46f984efd827517661c0e081a36014ca41af8vboxsync * attached images of the source VM as cloning targets. The IMedium code
80e46f984efd827517661c0e081a36014ca41af8vboxsync * take than care to merge any (possibly) existing parents into the new
80e46f984efd827517661c0e081a36014ca41af8vboxsync * image. */
80e46f984efd827517661c0e081a36014ca41af8vboxsync const ComObjPtr<Machine> &machine = machineList.at(i);
80e46f984efd827517661c0e081a36014ca41af8vboxsync /* If this is the Snapshot Machine we want to clone, we need to
80e46f984efd827517661c0e081a36014ca41af8vboxsync * create a new diff file for the new "current state". */
80e46f984efd827517661c0e081a36014ca41af8vboxsync const bool fCreateDiffs = (machine == pOldMachineState);
80e46f984efd827517661c0e081a36014ca41af8vboxsync /* Add all attachments of the different machines to a worker list. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a];
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Only harddisk's are of interest. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Valid medium attached? */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Create the medium task chain. In this case it will always
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * contain one image only. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Refresh the state so that the file size get read. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync mt.uIdx = UINT32_MAX; /* No read/write optimization possible. */
06782e19f5e2144408396dcec922c423c5ef9da8vboxsync /* Save the base name. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Save the current medium, for later cloning. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Update the progress info. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync updateProgressStats(mtc, fAttachLinked, uCount, uTotalWeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Append the list of images which have to be cloned. */
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync /* Add the save state files of this machine if there is one. */
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsyncHRESULT MachineCloneVMPrivate::queryMediasForMachineAndChildStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight)
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync /* This is basically a three step approach. First select all medias
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync * directly or indirectly involved in the clone. Second create a histogram
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync * of the usage of all that medias. Third select the medias which are
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync * directly attached or have more than one directly/indirectly used child
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync * in the new clone. Step one and two are done in the first loop.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Example of the histogram counts after going through 3 attachments from
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * bottom to top:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Whenever the histogram count is changing compared to the previous one we
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * need to include that image in the cloning step (Marked with <-). If we
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * start at zero even the directly attached images are automatically
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * included.
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * Note: This still leads to media chains which can have the same medium
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * included. This case is handled in "run" and therefor not critical, but
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * it leads to wrong progress infos which isn't nice. */
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync std::map<ComPtr<IMedium>, uint32_t> mediaHist; /* Our usage histogram for the medias */
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync const ComObjPtr<Machine> &machine = machineList.at(i);
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync /* If this is the Snapshot Machine we want to clone, we need to
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * create a new diff file for the new "current state". */
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync const bool fCreateDiffs = (machine == pOldMachineState);
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync /* Add all attachments (and their parents) of the different
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * machines to a worker list. */
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a];
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Only harddisk's are of interest. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Valid medium attached? */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Build a histogram of used medias and the parent chain. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Refresh the state so that the file size get read. */
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync /* Query next parent. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam());
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync /* Add the save state files of this machine if there is one. */
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync /* Build up the index list of the image chain. Unfortunately we can't do
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync * that in the previous loop, cause there we go from child -> parent and
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync * didn't know how many are between. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Print the histogram */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync for (it = mediaHist.begin(); it != mediaHist.end(); ++it)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = (*it).first->COMGETTER(Name)(bstrSrcName.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync RTPrintf("%ls: %d\n", bstrSrcName.raw(), (*it).second);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Go over every medium in the list and check if it either a directly
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * attached disk or has more than one children. If so it needs to be
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * replicated. Also we have to make sure that any direct or indirect
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * children knows of the new parent (which doesn't necessarily mean it
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * is a direct children in the source chain). */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = mt.pMedium->COMGETTER(Name)(bstrSrcName.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync RTPrintf("%ls: %d (%d)\n", bstrSrcName.raw(), hist, used);
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync /* Check if there is a "step" in the histogram when going the chain
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync * upwards. If so, we need this image, cause there is another branch
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * from here in the cloned VM. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Make sure we always using the old base name as new base name, even
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * if the base is a differencing image in the source VM (with the UUID
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * as name). */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = queryBaseName(newChain.last().pMedium, newChain.last().strBaseName);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Update the old medium chain with the updated one. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Update the progress info. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync updateProgressStats(mtc, fAttachLinked, uCount, uTotalWeight);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncHRESULT MachineCloneVMPrivate::queryMediasForAllStates(const RTCList<ComObjPtr<Machine> > &machineList, bool fAttachLinked, ULONG &uCount, ULONG &uTotalWeight)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* In this case we create a exact copy of the original VM. This means just
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * adding all directly and indirectly attached disk images to the worker
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync const ComObjPtr<Machine> &machine = machineList.at(i);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* If this is the Snapshot Machine we want to clone, we need to
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * create a new diff file for the new "current state". */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync const bool fCreateDiffs = (machine == pOldMachineState);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Add all attachments (and their parents) of the different
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * machines to a worker list. */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a];
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* Only harddisk's are of interest. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Valid medium attached? */
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Build up a child->parent list of this attachment. (Note: we are
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * not interested of any child's not attached to this VM. So this
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * will not create a full copy of the base/child relationship.) */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Refresh the state so that the file size get read. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Save the current medium, for later cloning. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Query next parent. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Update the progress info. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync updateProgressStats(mtc, fAttachLinked, uCount, uTotalWeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Append the list of images which have to be cloned. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Add the save state files of this machine if there is one. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Build up the index list of the image chain. Unfortunately we can't do
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * that in the previous loop, cause there we go from child -> parent and
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * didn't know how many are between. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsyncbool MachineCloneVMPrivate::findSnapshot(const settings::SnapshotsList &snl, const Guid &id, settings::Snapshot &sn) const
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return true;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return true;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return false;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncvoid MachineCloneVMPrivate::updateMACAddresses(settings::NetworkAdaptersList &nwl) const
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync const bool fNotNAT = options.contains(CloneOptions_KeepNATMACs);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncvoid MachineCloneVMPrivate::updateMACAddresses(settings::SnapshotsList &sl) const
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync updateMACAddresses(it->hardware.llNetworkAdapters);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncvoid MachineCloneVMPrivate::updateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const
48dafba24ef28f07a241e5857a43b327822574a8vboxsync settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncvoid MachineCloneVMPrivate::updateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync updateStorageLists(it->storage.llStorageControllers, bstrOldId, bstrNewId);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync updateSnapshotStorageLists(it->llChildSnapshots, bstrOldId, bstrNewId);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsyncvoid MachineCloneVMPrivate::updateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const
93771df67d4047d8b965665899b6a5bdf06ae277vboxsync updateStateFile(it->llChildSnapshots, id, strFile);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncHRESULT MachineCloneVMPrivate::createDifferencingMedium(const ComObjPtr<Machine> &pMachine, const ComObjPtr<Medium> &pParent, const Utf8Str &strSnapshotFolder, RTCList<ComObjPtr<Medium> > &newMedia, ComObjPtr<Medium> *ppDiff) const
1cd59fdf671ca60c64d77e3f7046aaecf7003824vboxsync // check validity of parent object
80e46f984efd827517661c0e081a36014ca41af8vboxsync rc = pParent->COMGETTER(Id)(bstrSrcId.asOutParam());
dbfa5765a2a72c30564ef1bd950720e89a06c96avboxsync Utf8StrFmt("%s%c", strSnapshotFolder.c_str(), RTPATH_DELIMITER),
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync MediumLockList *pMediumLockList(new MediumLockList());
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
3221176430afca4d1be145b04bf50163fab4fdb1vboxsync true /* fMediumLockWrite */,
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* this already registers the new diff image */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = pParent->createDiffStorage(diff, MediumVariant_Standard,
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync true /* aWait */);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* Remember created medium. */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync catch (...)
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync rc = VirtualBoxBase::handleUnexpectedExceptions(pMachine, RT_SRC_POS);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync/* static */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncint MachineCloneVMPrivate::copyStateFileProgress(unsigned uPercentage, void *pvUser)
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync ComObjPtr<Progress> pProgress = *static_cast< ComObjPtr<Progress>* >(pvUser);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync HRESULT rc = pProgress->COMGETTER(Canceled)(&fCanceled);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* If canceled by the user tell it to the copy operation. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Set the new process. */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync rc = pProgress->SetCurrentOperationProgress(uPercentage);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync// The public class
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync/////////////////////////////////////////////////////////////////////////////
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsyncMachineCloneVM::MachineCloneVM(ComObjPtr<Machine> pSrcMachine, ComObjPtr<Machine> pTrgMachine, CloneMode_T mode, const RTCList<CloneOptions_T> &opts)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync : d_ptr(new MachineCloneVMPrivate(this, pSrcMachine, pTrgMachine, mode, opts))
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsyncHRESULT MachineCloneVM::start(IProgress **pProgress)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @todo r=klaus this code cannot deal with someone crazy specifying
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * IMachine corresponding to a mutable machine as d->pSrcMachine */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync throw p->setError(E_INVALIDARG, "The source machine is mutable");
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Handle the special case that someone is requesting a _full_ clone
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * with all snapshots (and the current state), but uses a snapshot
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * machine (and not the current one) as source machine. In this case we
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * just replace the source (snapshot) machine with the current machine. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = d->pSrcMachine->COMGETTER(Id)(bstrSrcMachineId.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = d->pSrcMachine->getVirtualBox()->FindMachine(bstrSrcMachineId.raw(), newSrcMachine.asOutParam());
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync d->pSrcMachine = (Machine*)(IMachine*)newSrcMachine;
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync /* find machine object for current snapshot of current state */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync rc = d->pSrcMachine->COMGETTER(Id)(bstrSrcMachineId.asOutParam());
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync rc = d->pSrcMachine->getVirtualBox()->FindMachine(bstrSrcMachineId.raw(), pCurr.asOutParam());
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync rc = pCurrState->COMGETTER(CurrentSnapshot)(pSnapshot.asOutParam());
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync rc = pSnapshot->COMGETTER(Machine)(pCurrSnapMachine.asOutParam());
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync /* now check if there is a parent chain which leads to the
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync * snapshot machine defining the subtree. */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync rc = pSnapshot->COMGETTER(Machine)(pSnapMachine.asOutParam());
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync rc = pSnapshot->COMGETTER(Parent)(pSnapshot.asOutParam());
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* If the subtree is only the Current State simply use the
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * 'machine' case for cloning. It is easier to understand. */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* Lock the target machine early (so nobody mess around with it in the meantime). */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync AutoWriteLock trgLock(d->pTrgMachine COMMA_LOCKVAL_SRC_POS);
6febf3149010855617e4a37e2c49f93d68930d44vboxsync /* Add the current machine and all snapshot machines below this machine
6febf3149010855617e4a37e2c49f93d68930d44vboxsync * in a list for further processing. */
6febf3149010855617e4a37e2c49f93d68930d44vboxsync /* Include current state? */
dfb2e698385f22ba39053f27fe2711e463acd3a1vboxsync /* Should be done a depth copy with all child snapshots? */
dfb2e698385f22ba39053f27fe2711e463acd3a1vboxsync rc = d->pSrcMachine->COMGETTER(SnapshotCount)(&cSnapshots);
6febf3149010855617e4a37e2c49f93d68930d44vboxsync rc = d->pSrcMachine->FindSnapshot(Bstr(id).raw(), pSnapshot.asOutParam());
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync rc = pSnapshot->COMGETTER(Machine)(d->pOldMachineState.asOutParam());
63b785c3291332a86a9bc473e68f08121368898bvboxsync /* We have different approaches for getting the medias which needs to
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * be replicated based on the clone mode the user requested (this is
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * mostly about the full clone mode).
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * MachineState:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * - Only the images which are directly attached to an source VM will
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * be cloned. Any parent disks in the original chain will be merged
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * into the final cloned disk.
63b785c3291332a86a9bc473e68f08121368898bvboxsync * MachineAndChildStates:
63b785c3291332a86a9bc473e68f08121368898bvboxsync * - In this case we search for images which have more than one
63b785c3291332a86a9bc473e68f08121368898bvboxsync * children in the cloned VM or are directly attached to the new VM.
63b785c3291332a86a9bc473e68f08121368898bvboxsync * All others will be merged into the remaining images which are
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * This case is the most complicated one and needs several iterations
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * to make sure we are only cloning images which are really
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * necessary.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * AllStates:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * - All disks which are directly or indirectly attached to the
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * original VM are cloned.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Note: If you change something generic in one of the methods its
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * likely that it need to be changed in the others as well! */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync ULONG uCount = 2; /* One init task and the machine creation. */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync ULONG uTotalWeight = 2; /* The init task and the machine creation is worth one. */
825c2485cf84eec495985ffd605a1c9cddee8c32vboxsync bool fAttachLinked = d->options.contains(CloneOptions_Link); /* Linked clones requested? */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync switch (d->mode)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case CloneMode_MachineState: d->queryMediasForMachineState(machineList, fAttachLinked, uCount, uTotalWeight); break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case CloneMode_MachineAndChildStates: d->queryMediasForMachineAndChildStates(machineList, fAttachLinked, uCount, uTotalWeight); break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case CloneMode_AllStates: d->queryMediasForAllStates(machineList, fAttachLinked, uCount, uTotalWeight); break;
2294b1479e3fb6f4e9c9550b3e15f3d3a3f1fc24vboxsync /* Now create the progress project, so the user knows whats going on. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync static_cast<IMachine*>(d->pSrcMachine) /* aInitiator */,
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync true /* fCancellable */,
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync p->setError(VBOX_E_IPRT_ERROR, "Could not create machine clone thread (%Rrc)", vrc);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync AutoWriteLock trgLock(d->pTrgMachine COMMA_LOCKVAL_SRC_POS);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * - What about log files?
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Where should all the media go? */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync Utf8Str strTrgMachineFolder = d->pTrgMachine->getSettingsFileFull();
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTCList<ComObjPtr<Medium> > newMedia; /* All created images */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync RTCList<Utf8Str> newFiles; /* All extra created files (save states, ...) */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Copy all the configuration from this machine to an empty
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * configuration dataset. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync settings::MachineConfigFile trgMCF = *d->pSrcMachine->mData->pMachineConfigFile;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Reset media registry. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* If we got a valid snapshot id, replace the hardware/storage section
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * with the stuff from the snapshot. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (d->snapshotId.isValid() && !d->snapshotId.isZero())
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!d->findSnapshot(trgMCF.llFirstSnapshot, d->snapshotId, sn))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync p->tr("Could not find data to snapshots '%s'"), d->snapshotId.toString().c_str());
89de31eab6e960abcacfb70916598ae1c2e7f737vboxsync /* Remove any hint on snapshots. */
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync else if ( d->mode == CloneMode_MachineAndChildStates
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Copy the snapshot data to the current machine. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Current state is under root snapshot. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* There will be created a new differencing image based on this
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * snapshot. So reset the modified state. */
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync /* The snapshot will be the root one. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Generate new MAC addresses for all machines when not forbidden. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (!d->options.contains(CloneOptions_KeepAllMACs))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync d->updateMACAddresses(trgMCF.hardwareMachine.llNetworkAdapters);
825c2485cf84eec495985ffd605a1c9cddee8c32vboxsync /* When the current snapshot folder is absolute we reset it to the
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync * default relative folder. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if (RTPathStartsWithRoot(trgMCF.machineUserData.strSnapshotFolder.c_str()))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync trgMCF.machineUserData.strSnapshotFolder = "Snapshots";
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Set the new name. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync const Utf8Str strOldVMName = trgMCF.machineUserData.strName;
dad2c11c7cb6ce93d5db9a3266ed2b004d41c917vboxsync trgMCF.machineUserData.strName = d->pTrgMachine->mUserData->s.strName;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = d->pSrcMachine->COMGETTER(SnapshotFolder)(bstrSrcSnapshotFolder.asOutParam());
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* The absolute name of the snapshot folder. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync strTrgSnapshotFolder = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, trgMCF.machineUserData.strSnapshotFolder.c_str());
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Should we rename the disk names. */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync bool fKeepDiskNames = d->options.contains(CloneOptions_KeepDiskNames);
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync /* We need to create a map with the already created medias. This is
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * necessary, cause different snapshots could have the same
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * parents/parent chain. If a medium is in this map already, it isn't
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * cloned a second time, but simply used. */
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync typedef std::map<Utf8Str, ComObjPtr<Medium> > TStrMediumMap;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync typedef std::pair<Utf8Str, ComObjPtr<Medium> > TStrMediumPair;
b306a397b157898e6f769f640b0dfdffbf8beec7vboxsync rc = pMedium->COMGETTER(Name)(bstrSrcName.asOutParam());
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Cloning Disk '%ls' ..."), bstrSrcName.raw()).raw(), mt.uWeight);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync ComObjPtr<Medium> pLMedium = static_cast<Medium*>(pTmp);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* create the diff under the snapshot medium */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = d->createDifferencingMedium(p, pLMedium, strTrgSnapshotFolder,
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pDiff));
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync /* diff image has to be used... */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Attach the medium directly, as its type is not
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * subject to diff creation. */
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pLMedium));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Is a clone already there? */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync TStrMediumMap::iterator it = map.find(Utf8Str(bstrSrcId));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam());
b306a397b157898e6f769f640b0dfdffbf8beec7vboxsync com::SafeArray <MediumFormatCapabilities_T> mediumFormatCap;
b306a397b157898e6f769f640b0dfdffbf8beec7vboxsync rc = pSrcFormat->COMGETTER(Capabilities)(ComSafeArrayAsOutParam(mediumFormatCap));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Default format? */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync p->mParent->getDefaultHardDiskFormat(strDefaultFormat);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Is the source file based? */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File)
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync /* Yes, just use the source format. Otherwise the defaults
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync * will be used. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam());
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync rc = pMedium->COMGETTER(Variant)(ComSafeArrayAsOutParam(mediumVariant));
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync /* Check if we have to use another name. */
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync /* If the old disk name was in {uuid} format we also
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync * want the new name in this format, but with the
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync * updated id of course. If the old disk was called
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync * like the VM name, we change it to the new VM name.
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync * For all other disks we rename them with this
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync * template: "new name-disk1.vdi". */
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync strNewName = Utf8StrFmt("%s%s", trgMCF.machineUserData.strName.c_str(), RTPathSuffix(Utf8Str(bstrSrcName).c_str()));
39fa431e2dbe885a37b126ccd293f8e8255812a6vboxsync strSrcTest = strSrcTest.substr(1, strSrcTest.length() - 2);
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync strNewName = Utf8StrFmt("%s%s", newId.toStringCurly().c_str(), RTPathSuffix(strNewName.c_str()));
aceec09dd145a4d6fb14f2ea75a459cc88b334abvboxsync strNewName = Utf8StrFmt("%s-disk%d%s", trgMCF.machineUserData.strName.c_str(), ++cDisks,
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync /* Check if this medium comes from the snapshot folder, if
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync * so, put it there in the cloned machine as well.
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync * Otherwise it goes to the machine folder. */
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync Utf8Str strFile = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync rc = pMedium->COMGETTER(Location)(bstrSrcPath.asOutParam());
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync && RTPathStartsWith(Utf8Str(bstrSrcPath).c_str(), Utf8Str(bstrSrcSnapshotFolder).c_str())
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync strFile = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync /* Start creating the clone. */
bf88068260ded16af90b7da4867240fbdd9c8017vboxsync /* Update the new uuid. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /* Do the disk cloning. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync ComObjPtr<Medium> pLMedium = static_cast<Medium*>((IMedium*)pMedium);
const Utf8Str &strTrgSaveState = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, RTPathFilename(sst.strSaveStateFile.c_str()));
rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Copy save state file '%s' ..."), RTPathFilename(sst.strSaveStateFile.c_str())).raw(), sst.uWeight);
int vrc = RTFileCopyEx(sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), 0, MachineCloneVMPrivate::copyStateFileProgress, &d->pProgress);
p->tr("Could not copy state file '%s' to '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), vrc);
rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Create Machine Clone '%s' ..."), trgMCF.machineUserData.strName.c_str()).raw(), 1);
bool fNeedsGlobalSaveSettings = false;
mrc = p->setError(VBOX_E_IPRT_ERROR, p->tr("Could not delete file '%s' (%Rrc)"), newFiles.at(i).c_str(), vrc);
return mrc;