MachineImplCloneVM.cpp revision a6f38fd97cd5443acc4d60d672fdae1d52c6c6fa
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync/* $Id$ */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync/** @file
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * Implementation of MachineCloneVM
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync/*
aae8a6a38fd27661046ab1d06cb2cb5c096c40edvboxsync * Copyright (C) 2011 Oracle Corporation
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync *
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * available from http://www.virtualbox.org. This file is free software;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * General Public License (GPL) as published by the Free Software
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync#include "MachineImplCloneVM.h"
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync#include "VirtualBoxImpl.h"
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync#include "MediumImpl.h"
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync#include "HostImpl.h"
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync#include <iprt/path.h>
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync#include <iprt/dir.h>
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync#include <iprt/cpp/utils.h>
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync#include <VBox/com/list.h>
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync#include <VBox/com/MultiResult.h>
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync// typedefs
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync/////////////////////////////////////////////////////////////////////////////
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsynctypedef struct
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync{
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ComPtr<IMedium> pMedium;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ULONG uWeight;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync} MEDIUMTASK;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsynctypedef struct
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync{
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync RTCList<MEDIUMTASK> chain;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync bool fCreateDiffs;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync bool fAttachLinked;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync} MEDIUMTASKCHAIN;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsynctypedef struct
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync{
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync Guid snapshotUuid;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync Utf8Str strSaveStateFile;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ULONG uWeight;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync} SAVESTATETASK;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync// The private class
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync/////////////////////////////////////////////////////////////////////////////
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsyncstruct MachineCloneVMPrivate
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync{
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync MachineCloneVMPrivate(MachineCloneVM *a_q, ComObjPtr<Machine> &a_pSrcMachine, ComObjPtr<Machine> &a_pTrgMachine, CloneMode_T a_mode, const RTCList<CloneOptions_T> &opts)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync : q_ptr(a_q)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync , p(a_pSrcMachine)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync , pSrcMachine(a_pSrcMachine)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync , pTrgMachine(a_pTrgMachine)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync , mode(a_mode)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync , options(opts)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {}
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Thread management */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync int startWorker()
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync return RTThreadCreate(NULL,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync MachineCloneVMPrivate::workerThread,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync static_cast<void*>(this),
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync 0,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync RTTHREADTYPE_MAIN_WORKER,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync 0,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync "MachineClone");
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync static int workerThread(RTTHREAD /* Thread */, void *pvUser)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync MachineCloneVMPrivate *pTask = static_cast<MachineCloneVMPrivate*>(pvUser);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync AssertReturn(pTask, VERR_INVALID_POINTER);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync HRESULT rc = pTask->q_ptr->run();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync pTask->pProgress->notifyComplete(rc);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync pTask->q_ptr->destroy();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync return VINF_SUCCESS;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Private helper methods */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync HRESULT createMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComObjPtr<Machine> > &machineList) const;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync settings::Snapshot findSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync void updateMACAddresses(settings::NetworkAdaptersList &nwl) const;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync void updateMACAddresses(settings::SnapshotsList &sl) const;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync void updateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync void updateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync void updateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync static int copyStateFileProgress(unsigned uPercentage, void *pvUser);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Private q and parent pointer */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync MachineCloneVM *q_ptr;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComObjPtr<Machine> p;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync /* Private helper members */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComObjPtr<Machine> pSrcMachine;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComObjPtr<Machine> pTrgMachine;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComPtr<IMachine> pOldMachineState;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComObjPtr<Progress> pProgress;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync Guid snapshotId;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync CloneMode_T mode;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync RTCList<CloneOptions_T> options;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync RTCList<MEDIUMTASKCHAIN> llMedias;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync RTCList<SAVESTATETASK> llSaveStateFiles; /* Snapshot UUID -> File path */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync};
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsyncHRESULT MachineCloneVMPrivate::createMachineList(const ComPtr<ISnapshot> &pSnapshot, RTCList< ComObjPtr<Machine> > &machineList) const
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync{
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync HRESULT rc = S_OK;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync Bstr name;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = pSnapshot->COMGETTER(Name)(name.asOutParam());
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) return rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComPtr<IMachine> pMachine;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = pSnapshot->COMGETTER(Machine)(pMachine.asOutParam());
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) return rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync machineList.append((Machine*)(IMachine*)pMachine);
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync SafeIfaceArray<ISnapshot> sfaChilds;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = pSnapshot->COMGETTER(Children)(ComSafeArrayAsOutParam(sfaChilds));
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) return rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync for (size_t i = 0; i < sfaChilds.size(); ++i)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync {
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = createMachineList(sfaChilds[i], machineList);
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) return rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync }
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync return rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync}
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsyncsettings::Snapshot MachineCloneVMPrivate::findSnapshot(settings::MachineConfigFile *pMCF, const settings::SnapshotsList &snl, const Guid &id) const
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync{
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync settings::SnapshotsList::const_iterator it;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync for (it = snl.begin(); it != snl.end(); ++it)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync {
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (it->uuid == id)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync return *it;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync else if (!it->llChildSnapshots.empty())
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync return findSnapshot(pMCF, it->llChildSnapshots, id);
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync }
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync return settings::Snapshot();
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync}
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsyncvoid MachineCloneVMPrivate::updateMACAddresses(settings::NetworkAdaptersList &nwl) const
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync{
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync const bool fNotNAT = options.contains(CloneOptions_KeepNATMACs);
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync settings::NetworkAdaptersList::iterator it;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync for (it = nwl.begin(); it != nwl.end(); ++it)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync {
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if ( fNotNAT
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync && it->mode == NetworkAttachmentType_NAT)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync continue;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync Host::generateMACAddress(it->strMACAddress);
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync }
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync}
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsyncvoid MachineCloneVMPrivate::updateMACAddresses(settings::SnapshotsList &sl) const
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync{
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync settings::SnapshotsList::iterator it;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync for (it = sl.begin(); it != sl.end(); ++it)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync updateMACAddresses(it->hardware.llNetworkAdapters);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (!it->llChildSnapshots.empty())
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync updateMACAddresses(it->llChildSnapshots);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync}
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsyncvoid MachineCloneVMPrivate::updateStorageLists(settings::StorageControllersList &sc, const Bstr &bstrOldId, const Bstr &bstrNewId) const
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync{
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync settings::StorageControllersList::iterator it3;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync for (it3 = sc.begin();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync it3 != sc.end();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ++it3)
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync settings::AttachedDevicesList::iterator it4;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync for (it4 = llAttachments.begin();
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync it4 != llAttachments.end();
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ++it4)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if ( it4->deviceType == DeviceType_HardDisk
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync && it4->uuid == bstrOldId)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync it4->uuid = bstrNewId;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync}
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsyncvoid MachineCloneVMPrivate::updateSnapshotStorageLists(settings::SnapshotsList &sl, const Bstr &bstrOldId, const Bstr &bstrNewId) const
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync{
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync settings::SnapshotsList::iterator it;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync for ( it = sl.begin();
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync it != sl.end();
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync ++it)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync updateStorageLists(it->storage.llStorageControllers, bstrOldId, bstrNewId);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (!it->llChildSnapshots.empty())
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync updateSnapshotStorageLists(it->llChildSnapshots, bstrOldId, bstrNewId);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync}
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsyncvoid MachineCloneVMPrivate::updateStateFile(settings::SnapshotsList &snl, const Guid &id, const Utf8Str &strFile) const
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync{
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync settings::SnapshotsList::iterator it;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync for (it = snl.begin(); it != snl.end(); ++it)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (it->uuid == id)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync it->strStateFile = strFile;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync else if (!it->llChildSnapshots.empty())
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync updateStateFile(it->llChildSnapshots, id, strFile);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync}
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync/* static */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsyncint MachineCloneVMPrivate::copyStateFileProgress(unsigned uPercentage, void *pvUser)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync{
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ComObjPtr<Progress> pProgress = *static_cast< ComObjPtr<Progress>* >(pvUser);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync BOOL fCanceled = false;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync HRESULT rc = pProgress->COMGETTER(Canceled)(&fCanceled);
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync if (FAILED(rc)) return VERR_GENERAL_FAILURE;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* If canceled by the user tell it to the copy operation. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (fCanceled) return VERR_CANCELLED;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Set the new process. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = pProgress->SetCurrentOperationProgress(uPercentage);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) return VERR_GENERAL_FAILURE;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync return VINF_SUCCESS;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync}
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
90ecd36a6e45ec33526541f68cf89c21ec578f83vboxsync// The public class
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync/////////////////////////////////////////////////////////////////////////////
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsyncMachineCloneVM::MachineCloneVM(ComObjPtr<Machine> pSrcMachine, ComObjPtr<Machine> pTrgMachine, CloneMode_T mode, const RTCList<CloneOptions_T> &opts)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync : d_ptr(new MachineCloneVMPrivate(this, pSrcMachine, pTrgMachine, mode, opts))
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync{
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync}
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsyncMachineCloneVM::~MachineCloneVM()
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync{
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync delete d_ptr;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync}
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsyncHRESULT MachineCloneVM::start(IProgress **pProgress)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync{
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync DPTR(MachineCloneVM);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ComObjPtr<Machine> &p = d->p;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync HRESULT rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync try
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Handle the special case that someone is requesting a _full_ clone
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * with all snapshots (and the current state), but uses a snapshot
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * machine (and not the current one) as source machine. In this case we
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * just replace the source (snapshot) machine with the current machine. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if ( d->mode == CloneMode_AllStates
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync && d->pSrcMachine->isSnapshotMachine())
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Bstr bstrSrcMachineId;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = d->pSrcMachine->COMGETTER(Id)(bstrSrcMachineId.asOutParam());
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ComPtr<IMachine> newSrcMachine;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = d->pSrcMachine->getVirtualBox()->FindMachine(bstrSrcMachineId.raw(), newSrcMachine.asOutParam());
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync d->pSrcMachine = (Machine*)(IMachine*)newSrcMachine;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Lock the target machine early (so nobody mess around with it in the meantime). */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync AutoWriteLock trgLock(d->pTrgMachine COMMA_LOCKVAL_SRC_POS);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync if (d->pSrcMachine->isSnapshotMachine())
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync d->snapshotId = d->pSrcMachine->getSnapshotId();
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync /* Add the current machine and all snapshot machines below this machine
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync * in a list for further processing. */
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync RTCList< ComObjPtr<Machine> > machineList;
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync /* Include current state? */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if ( d->mode == CloneMode_MachineState
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync || d->mode == CloneMode_AllStates)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync machineList.append(d->pSrcMachine);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Should be done a depth copy with all child snapshots? */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if ( d->mode == CloneMode_MachineAndChildStates
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync || d->mode == CloneMode_AllStates)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ULONG cSnapshots = 0;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = d->pSrcMachine->COMGETTER(SnapshotCount)(&cSnapshots);
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (cSnapshots > 0)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Utf8Str id;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if ( d->mode == CloneMode_MachineAndChildStates
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync && !d->snapshotId.isEmpty())
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync id = d->snapshotId.toString();
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComPtr<ISnapshot> pSnapshot;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = d->pSrcMachine->FindSnapshot(Bstr(id).raw(), pSnapshot.asOutParam());
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) throw rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = d->createMachineList(pSnapshot, machineList);
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) throw rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (d->mode == CloneMode_MachineAndChildStates)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync {
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = pSnapshot->COMGETTER(Machine)(d->pOldMachineState.asOutParam());
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) throw rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync }
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync }
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync }
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync /* Go over every machine and walk over every attachment this machine has. */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ULONG uCount = 2; /* One init task and the machine creation. */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ULONG uTotalWeight = 2; /* The init task and the machine creation is worth one. */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync for (size_t i = 0; i < machineList.size(); ++i)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync {
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync ComObjPtr<Machine> machine = machineList.at(i);
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync /* If this is the Snapshot Machine we want to clone, we need to
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync * create a new diff file for the new "current state". */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync bool fCreateDiffs = false;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (machine == d->pOldMachineState)
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync fCreateDiffs = true;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync /* If we want to create a linked clone just attach the medium
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync * associated with the snapshot. The rest is taken care of by
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync * attach already, so no need to duplicate this. */
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync bool fAttachLinked = false;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (d->options.contains(CloneOptions_Link))
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync fAttachLinked = true;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync SafeIfaceArray<IMediumAttachment> sfaAttachments;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync rc = machine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(sfaAttachments));
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync if (FAILED(rc)) throw rc;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync /* Add all attachments (and their parents) of the different
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync * machines to a worker list. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync for (size_t a = 0; a < sfaAttachments.size(); ++a)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync const ComPtr<IMediumAttachment> &pAtt = sfaAttachments[a];
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync DeviceType_T type;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = pAtt->COMGETTER(Type)(&type);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Only harddisk's are of interest. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (type != DeviceType_HardDisk)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync continue;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Valid medium attached? */
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync ComPtr<IMedium> pSrcMedium;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pAtt->COMGETTER(Medium)(pSrcMedium.asOutParam());
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (FAILED(rc)) throw rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (pSrcMedium.isNull())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync continue;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Build up a child->parent list of this attachment. (Note: we are
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * not interested of any child's not attached to this VM. So this
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * will not create a full copy of the base/child relationship.) */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync MEDIUMTASKCHAIN mtc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mtc.fCreateDiffs = fCreateDiffs;
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync mtc.fAttachLinked = fAttachLinked;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (d->mode == CloneMode_MachineState)
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Refresh the state so that the file size get read. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync MediumState_T e;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pSrcMedium->RefreshState(&e);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (FAILED(rc)) throw rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync LONG64 lSize;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = pSrcMedium->COMGETTER(Size)(&lSize);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (FAILED(rc)) throw rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync /* Save the current medium, for later cloning. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync MEDIUMTASK mt;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mt.pMedium = pSrcMedium;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (fAttachLinked)
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mt.uWeight = 0; /* dummy */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync else
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mt.uWeight = (lSize + _1M - 1) / _1M;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mtc.chain.append(mt);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync else
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /** @todo r=klaus this puts way too many images in the list
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * when cloning a snapshot (sub)tree, which means that more
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * images are cloned than necessary. It is just the easiest
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * way to get a working VM, as getting the image
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * parent/child relationships right for only the bare
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * minimum cloning is rather tricky. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync while (!pSrcMedium.isNull())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Refresh the state so that the file size get read. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync MediumState_T e;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pSrcMedium->RefreshState(&e);
0005b7c81d5621b5c6e0b38ce3cbcabf7e883fd3vboxsync if (FAILED(rc)) throw rc;
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync LONG64 lSize;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pSrcMedium->COMGETTER(Size)(&lSize);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (FAILED(rc)) throw rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Save the current medium, for later cloning. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync MEDIUMTASK mt;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mt.pMedium = pSrcMedium;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mt.uWeight = (lSize + _1M - 1) / _1M;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mtc.chain.append(mt);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Query next parent. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pSrcMedium->COMGETTER(Parent)(pSrcMedium.asOutParam());
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (FAILED(rc)) throw rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (fAttachLinked)
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Implicit diff creation as part of attach is a pretty cheap
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * operation, and does only need one operation per attachment. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ++uCount;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uTotalWeight += 1; /* 1MB per attachment */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync else
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Currently the copying of diff images involves reading at least
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * the biggest parent in the previous chain. So even if the new
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * diff image is small in size, it could need some time to create
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * it. Adding the biggest size in the chain should balance this a
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * little bit more, i.e. the weight is the sum of the data which
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * needs to be read and written. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uint64_t uMaxSize = 0;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync for (size_t e = mtc.chain.size(); e > 0; --e)
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync MEDIUMTASK &mt = mtc.chain.at(e - 1);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync mt.uWeight += uMaxSize;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Calculate progress data */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ++uCount;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uTotalWeight += mt.uWeight;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Save the max size for better weighting of diff image
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * creation. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uMaxSize = RT_MAX(uMaxSize, mt.uWeight);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync d->llMedias.append(mtc);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync Bstr bstrSrcSaveStatePath;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync rc = machine->COMGETTER(StateFilePath)(bstrSrcSaveStatePath.asOutParam());
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (FAILED(rc)) throw rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (!bstrSrcSaveStatePath.isEmpty())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync SAVESTATETASK sst;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync sst.snapshotUuid = machine->getSnapshotId();
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync sst.strSaveStateFile = bstrSrcSaveStatePath;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uint64_t cbSize;
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync int vrc = RTFileQuerySize(sst.strSaveStateFile.c_str(), &cbSize);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (RT_FAILURE(vrc))
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync throw p->setError(VBOX_E_IPRT_ERROR, p->tr("Could not query file size of '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), vrc);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* same rule as above: count both the data which needs to
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * be read and written */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync sst.uWeight = 2 * (cbSize + _1M - 1) / _1M;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync d->llSaveStateFiles.append(sst);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ++uCount;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uTotalWeight += sst.uWeight;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = d->pProgress.createObject();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (FAILED(rc)) throw rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = d->pProgress->init(p->getVirtualBox(),
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync static_cast<IMachine*>(d->pSrcMachine) /* aInitiator */,
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync Bstr(p->tr("Cloning Machine")).raw(),
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync true /* fCancellable */,
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uCount,
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync uTotalWeight,
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync Bstr(p->tr("Initialize Cloning")).raw(),
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync 1);
0005b7c81d5621b5c6e0b38ce3cbcabf7e883fd3vboxsync if (FAILED(rc)) throw rc;
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync int vrc = d->startWorker();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (RT_FAILURE(vrc))
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync p->setError(VBOX_E_IPRT_ERROR, "Could not create machine clone thread (%Rrc)", vrc);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync catch (HRESULT rc2)
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = rc2;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (SUCCEEDED(rc))
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync d->pProgress.queryInterfaceTo(pProgress);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync return rc;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync}
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsyncHRESULT MachineCloneVM::run()
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync{
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync DPTR(MachineCloneVM);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ComObjPtr<Machine> &p = d->p;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync AutoCaller autoCaller(p);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (FAILED(autoCaller.rc())) return autoCaller.rc();
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync AutoReadLock srcLock(p COMMA_LOCKVAL_SRC_POS);
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync AutoWriteLock trgLock(d->pTrgMachine COMMA_LOCKVAL_SRC_POS);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync HRESULT rc = S_OK;
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /*
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * Todo:
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync * - What about log files?
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Where should all the media go? */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync Utf8Str strTrgSnapshotFolder;
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync Utf8Str strTrgMachineFolder = d->pTrgMachine->getSettingsFileFull();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync strTrgMachineFolder.stripFilename();
ee53c59753e01c16a61332987bf2c406f153392evboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync RTCList<ComObjPtr<Medium> > newMedia; /* All created images */
ee53c59753e01c16a61332987bf2c406f153392evboxsync RTCList<Utf8Str> newFiles; /* All extra created files (save states, ...) */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync try
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync {
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync /* Copy all the configuration from this machine to an empty
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * configuration dataset. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync settings::MachineConfigFile trgMCF = *d->pSrcMachine->mData->pMachineConfigFile;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Reset media registry. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.mediaRegistry.llHardDisks.clear();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* If we got a valid snapshot id, replace the hardware/storage section
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * with the stuff from the snapshot. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync settings::Snapshot sn;
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync if (!d->snapshotId.isEmpty())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync sn = d->findSnapshot(&trgMCF, trgMCF.llFirstSnapshot, d->snapshotId);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (d->mode == CloneMode_MachineState)
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (!sn.uuid.isEmpty())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.hardwareMachine = sn.hardware;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.storageMachine = sn.storage;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Remove any hint on snapshots. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.llFirstSnapshot.clear();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.uuidCurrentSnapshot.clear();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync else if ( d->mode == CloneMode_MachineAndChildStates
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync && !sn.uuid.isEmpty())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Copy the snapshot data to the current machine. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.hardwareMachine = sn.hardware;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.storageMachine = sn.storage;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* The snapshot will be the root one. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.uuidCurrentSnapshot = sn.uuid;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.llFirstSnapshot.clear();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.llFirstSnapshot.push_back(sn);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
0005b7c81d5621b5c6e0b38ce3cbcabf7e883fd3vboxsync
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync /* Generate new MAC addresses for all machines when not forbidden. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (!d->options.contains(CloneOptions_KeepAllMACs))
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync d->updateMACAddresses(trgMCF.hardwareMachine.llNetworkAdapters);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync d->updateMACAddresses(trgMCF.llFirstSnapshot);
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync }
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync /* When the current snapshot folder is absolute we reset it to the
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync * default relative folder. */
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync if (RTPathStartsWithRoot(trgMCF.machineUserData.strSnapshotFolder.c_str()))
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync trgMCF.machineUserData.strSnapshotFolder = "Snapshots";
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.strStateFile = "";
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Force writing of setting file. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.fCurrentStateModified = true;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Set the new name. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync const Utf8Str strOldVMName = trgMCF.machineUserData.strName;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.machineUserData.strName = d->pTrgMachine->mUserData->s.strName;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync trgMCF.uuid = d->pTrgMachine->mData->mUuid;
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync Bstr bstrSrcSnapshotFolder;
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync rc = d->pSrcMachine->COMGETTER(SnapshotFolder)(bstrSrcSnapshotFolder.asOutParam());
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync if (FAILED(rc)) throw rc;
ad4f6ac2063d9b48efd9c3193442136a8c7c890avboxsync /* The absolute name of the snapshot folder. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync strTrgSnapshotFolder = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, trgMCF.machineUserData.strSnapshotFolder.c_str());
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Should we rename the disk names. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync bool fKeepDiskNames = d->options.contains(CloneOptions_KeepDiskNames);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* We need to create a map with the already created medias. This is
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * necessary, cause different snapshots could have the same
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * parents/parent chain. If a medium is in this map already, it isn't
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync * cloned a second time, but simply used. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync typedef std::map<Utf8Str, ComObjPtr<Medium> > TStrMediumMap;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync typedef std::pair<Utf8Str, ComObjPtr<Medium> > TStrMediumPair;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync TStrMediumMap map;
447d6c76d88201b58c0bd7b0c8621088cf428951vboxsync GuidList llRegistriesThatNeedSaving;
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync size_t cDisks = 0;
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync for (size_t i = 0; i < d->llMedias.size(); ++i)
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync {
455d9b835215b524a2fec962638d4d75b81dc3ccvboxsync const MEDIUMTASKCHAIN &mtc = d->llMedias.at(i);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ComObjPtr<Medium> pNewParent;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync for (size_t a = mtc.chain.size(); a > 0; --a)
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync const MEDIUMTASK &mt = mtc.chain.at(a - 1);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ComPtr<IMedium> pMedium = mt.pMedium;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync Bstr bstrSrcName;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pMedium->COMGETTER(Name)(bstrSrcName.asOutParam());
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Cloning Disk '%ls' ..."), bstrSrcName.raw()).raw(), mt.uWeight);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (FAILED(rc)) throw rc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync Bstr bstrSrcId;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (mtc.fAttachLinked)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync IMedium *pTmp = pMedium;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ComObjPtr<Medium> pLMedium = static_cast<Medium*>(pTmp);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (pLMedium.isNull())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync throw E_POINTER;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (pLMedium->isReadOnly())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ComObjPtr<Medium> pDiff;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* create the diff under the snapshot medium */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = createDiffHelper(pLMedium, strTrgSnapshotFolder,
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync &newMedia, &pDiff);
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pDiff));
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* diff image has to be used... */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync pNewParent = pDiff;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync else
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Attach the medium directly, as its type is not
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * subject to diff creation. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync newMedia.append(pLMedium);
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pLMedium));
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync pNewParent = pLMedium;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync else
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Is a clone already there? */
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync TStrMediumMap::iterator it = map.find(Utf8Str(bstrSrcId));
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (it != map.end())
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync pNewParent = it->second;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync else
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ComPtr<IMediumFormat> pSrcFormat;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pMedium->COMGETTER(MediumFormat)(pSrcFormat.asOutParam());
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ULONG uSrcCaps = 0;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync rc = pSrcFormat->COMGETTER(Capabilities)(&uSrcCaps);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* Default format? */
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync Utf8Str strDefaultFormat;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync p->mParent->getDefaultHardDiskFormat(strDefaultFormat);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync Bstr bstrSrcFormat(strDefaultFormat);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync ULONG srcVar = MediumVariant_Standard;
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync /* Is the source file based? */
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync if ((uSrcCaps & MediumFormatCapabilities_File) == MediumFormatCapabilities_File)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync /* Yes, just use the source format. Otherwise the defaults
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * will be used. */
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync rc = pMedium->COMGETTER(Format)(bstrSrcFormat.asOutParam());
d2c6b2e8826a5ef34170fef0c72c3fc7c5c1b46avboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = pMedium->COMGETTER(Variant)(&srcVar);
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync Guid newId;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync newId.create();
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Utf8Str strNewName(bstrSrcName);
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (!fKeepDiskNames)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync /* If the old disk name was in {uuid} format we also
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * want the new name in this format, but with the
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * updated id of course. If the old disk was called
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync * like the VM name, we change it to the new VM name.
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync * For all other disks we rename them with this
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * template: "new name-disk1.vdi". */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Utf8Str strSrcTest = Utf8Str(bstrSrcName).stripExt();
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (strSrcTest == strOldVMName)
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync strNewName = Utf8StrFmt("%s%s", trgMCF.machineUserData.strName.c_str(), RTPathExt(Utf8Str(bstrSrcName).c_str()));
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync else if ( strSrcTest.startsWith("{")
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync && strSrcTest.endsWith("}"))
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync {
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync strSrcTest = strSrcTest.substr(1, strSrcTest.length() - 2);
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync if (isValidGuid(strSrcTest))
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync strNewName = Utf8StrFmt("%s%s", newId.toStringCurly().c_str(), RTPathExt(strNewName.c_str()));
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync }
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync else
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync strNewName = Utf8StrFmt("%s-disk%d%s", trgMCF.machineUserData.strName.c_str(), ++cDisks, RTPathExt(Utf8Str(bstrSrcName).c_str()));
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Check if this medium comes from the snapshot folder, if
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync * so, put it there in the cloned machine as well.
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync * Otherwise it goes to the machine folder. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Bstr bstrSrcPath;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Utf8Str strFile = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync rc = pMedium->COMGETTER(Location)(bstrSrcPath.asOutParam());
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync if (FAILED(rc)) throw rc;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if ( !bstrSrcPath.isEmpty()
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync && RTPathStartsWith(Utf8Str(bstrSrcPath).c_str(), Utf8Str(bstrSrcSnapshotFolder).c_str()))
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync strFile = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync else
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync strFile = Utf8StrFmt("%s%c%s", strTrgMachineFolder.c_str(), RTPATH_DELIMITER, strNewName.c_str());
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync
2afbe132eb7931e0125141eabe3a48e08f1ffab5vboxsync /* Start creating the clone. */
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync ComObjPtr<Medium> pTarget;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = pTarget.createObject();
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = pTarget->init(p->mParent,
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Utf8Str(bstrSrcFormat),
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync strFile,
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync Guid::Empty, /* empty media registry */
1759f65b60e18f669f6d569aebd4fb7217ab414fvboxsync NULL /* llRegistriesThatNeedSaving */);
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync if (FAILED(rc)) throw rc;
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Update the new uuid. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync pTarget->updateId(newId);
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync srcLock.release();
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync /* Do the disk cloning. */
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync ComPtr<IProgress> progress2;
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync rc = pMedium->CloneTo(pTarget,
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync srcVar,
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync pNewParent,
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync progress2.asOutParam());
8c97c335e49609421316d92d2e0aff3e7f8eed04vboxsync if (FAILED(rc)) throw rc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Wait until the async process has finished. */
badc8f586d7b8d9606f5d1611bb5d429196fe18bvboxsync rc = d->pProgress->WaitForAsyncProgressCompletion(progress2);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync srcLock.acquire();
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (FAILED(rc)) throw rc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Check the result of the async process. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync LONG iRc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync rc = progress2->COMGETTER(ResultCode)(&iRc);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(iRc))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* If the thread of the progress object has an error, then
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * retrieve the error info from there, or it'll be lost. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ProgressErrorInfo info(progress2);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync throw p->setError(iRc, Utf8Str(info.getText()).c_str());
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Remember created medium. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync newMedia.append(pTarget);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Get the medium type from the source and set it to the
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * new medium. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync MediumType_T type;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = pMedium->COMGETTER(Type)(&type);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = pTarget->COMSETTER(Type)(type);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync map.insert(TStrMediumPair(Utf8Str(bstrSrcId), pTarget));
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* register the new harddisk */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync AutoWriteLock tlock(p->mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = p->mParent->registerHardDisk(pTarget, NULL /* pllRegistriesThatNeedSaving */);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* This medium becomes the parent of the next medium in the
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * chain. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync pNewParent = pTarget;
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Create diffs for the last image chain. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (mtc.fCreateDiffs)
90eb38579e280c6a0e466177b2a9632ab9eb8c44vboxsync {
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (pNewParent->isReadOnly())
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync ComObjPtr<Medium> pDiff;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = createDiffHelper(pNewParent, strTrgSnapshotFolder,
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync &newMedia, &pDiff);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (FAILED(rc)) throw rc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* diff image has to be used... */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync pNewParent = pDiff;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync else
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Attach the medium directly, as its type is not
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync * subject to diff creation. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync newMedia.append(pNewParent);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync Bstr bstrSrcId;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = mtc.chain.first().pMedium->COMGETTER(Id)(bstrSrcId.asOutParam());
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync Bstr bstrTrgId;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = pNewParent->COMGETTER(Id)(bstrTrgId.asOutParam());
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* We have to patch the configuration, so it contains the new
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * medium uuid instead of the old one. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync d->updateStorageLists(trgMCF.storageMachine.llStorageControllers, bstrSrcId, bstrTrgId);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync d->updateSnapshotStorageLists(trgMCF.llFirstSnapshot, bstrSrcId, bstrTrgId);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Make sure all disks know of the new machine uuid. We do this last to
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * be able to change the medium type above. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync for (size_t i = newMedia.size(); i > 0; --i)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync const ComObjPtr<Medium> &pMedium = newMedia.at(i - 1);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync AutoCaller mac(pMedium);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(mac.rc())) throw mac.rc();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync AutoWriteLock mlock(pMedium COMMA_LOCKVAL_SRC_POS);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync Guid uuid = d->pTrgMachine->mData->mUuid;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (d->options.contains(CloneOptions_Link))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ComObjPtr<Medium> pParent = pMedium->getParent();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync mlock.release();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (!pParent.isNull())
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync AutoCaller mac2(pParent);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(mac2.rc())) throw mac2.rc();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync AutoReadLock mlock2(pParent COMMA_LOCKVAL_SRC_POS);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (pParent->getFirstRegistryMachineId(uuid))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync VirtualBox::addGuidToListUniquely(llRegistriesThatNeedSaving, uuid);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync mlock.acquire();
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync pMedium->addRegistry(uuid, false /* fRecurse */);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Check if a snapshot folder is necessary and if so doesn't already
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * exists. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if ( !d->llSaveStateFiles.isEmpty()
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync && !RTDirExists(strTrgSnapshotFolder.c_str()))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync int vrc = RTDirCreateFullPath(strTrgSnapshotFolder.c_str(), 0777);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (RT_FAILURE(vrc))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync throw p->setError(VBOX_E_IPRT_ERROR,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync p->tr("Could not create snapshots folder '%s' (%Rrc)"), strTrgSnapshotFolder.c_str(), vrc);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Clone all save state files. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync for (size_t i = 0; i < d->llSaveStateFiles.size(); ++i)
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync SAVESTATETASK sst = d->llSaveStateFiles.at(i);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync const Utf8Str &strTrgSaveState = Utf8StrFmt("%s%c%s", strTrgSnapshotFolder.c_str(), RTPATH_DELIMITER, RTPathFilename(sst.strSaveStateFile.c_str()));
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Move to next sub-operation. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Copy save state file '%s' ..."), RTPathFilename(sst.strSaveStateFile.c_str())).raw(), sst.uWeight);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Copy the file only if it was not copied already. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (!newFiles.contains(strTrgSaveState.c_str()))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync int vrc = RTFileCopyEx(sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), 0, MachineCloneVMPrivate::copyStateFileProgress, &d->pProgress);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (RT_FAILURE(vrc))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync throw p->setError(VBOX_E_IPRT_ERROR,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync p->tr("Could not copy state file '%s' to '%s' (%Rrc)"), sst.strSaveStateFile.c_str(), strTrgSaveState.c_str(), vrc);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync newFiles.append(strTrgSaveState);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Update the path in the configuration either for the current
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * machine state or the snapshots. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (sst.snapshotUuid.isEmpty())
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync trgMCF.strStateFile = strTrgSaveState;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync else
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync d->updateStateFile(trgMCF.llFirstSnapshot, sst.snapshotUuid, strTrgSaveState);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = d->pProgress->SetNextOperation(BstrFmt(p->tr("Create Machine Clone '%s' ..."), trgMCF.machineUserData.strName.c_str()).raw(), 1);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* After modifying the new machine config, we can copy the stuff
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * over to the new machine. The machine have to be mutable for
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * this. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = d->pTrgMachine->checkStateDependency(p->MutableStateDep);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync rc = d->pTrgMachine->loadMachineDataFromSettings(trgMCF,
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync &d->pTrgMachine->mData->mUuid);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Now save the new configuration to disk. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = d->pTrgMachine->SaveSettings();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync trgLock.release();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (!llRegistriesThatNeedSaving.empty())
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync srcLock.release();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = p->mParent->saveRegistries(llRegistriesThatNeedSaving);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync catch (HRESULT rc2)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = rc2;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync catch (...)
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync MultiResult mrc(rc);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Cleanup on failure (CANCEL also) */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync int vrc = VINF_SUCCESS;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Delete all created files. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync for (size_t i = 0; i < newFiles.size(); ++i)
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync vrc = RTFileDelete(newFiles.at(i).c_str());
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (RT_FAILURE(vrc))
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync mrc = p->setError(VBOX_E_IPRT_ERROR, p->tr("Could not delete file '%s' (%Rrc)"), newFiles.at(i).c_str(), vrc);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Delete all already created medias. (Reverse, cause there could be
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync * parent->child relations.) */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync for (size_t i = newMedia.size(); i > 0; --i)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync const ComObjPtr<Medium> &pMedium = newMedia.at(i - 1);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync mrc = pMedium->deleteStorage(NULL /* aProgress */,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync true /* aWait */,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync NULL /* llRegistriesThatNeedSaving */);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync pMedium->Close();
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync /* Delete the snapshot folder when not empty. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (!strTrgSnapshotFolder.isEmpty())
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync RTDirRemove(strTrgSnapshotFolder.c_str());
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync /* Delete the machine folder when not empty. */
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync RTDirRemove(strTrgMachineFolder.c_str());
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync return mrc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync}
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsyncHRESULT MachineCloneVM::createDiffHelper(const ComObjPtr<Medium> &pParent,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync const Utf8Str &strSnapshotFolder,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync RTCList< ComObjPtr<Medium> > *pNewMedia,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ComObjPtr<Medium> *ppDiff)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync{
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync DPTR(MachineCloneVM);
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ComObjPtr<Machine> &p = d->p;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync HRESULT rc = S_OK;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync try
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync Bstr bstrSrcId;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = pParent->COMGETTER(Id)(bstrSrcId.asOutParam());
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync if (FAILED(rc)) throw rc;
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync ComObjPtr<Medium> diff;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync diff.createObject();
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync rc = diff->init(p->mParent,
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync pParent->getPreferredDiffFormat(),
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync Utf8StrFmt("%s%c", strSnapshotFolder.c_str(), RTPATH_DELIMITER),
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync Guid::Empty, /* empty media registry */
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync NULL); /* pllRegistriesThatNeedSaving */
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync if (FAILED(rc)) throw rc;
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync MediumLockList *pMediumLockList(new MediumLockList());
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync rc = diff->createMediumLockList(true /* fFailIfInaccessible */,
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync true /* fMediumLockWrite */,
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync pParent,
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync *pMediumLockList);
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync if (FAILED(rc)) throw rc;
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync rc = pMediumLockList->Lock();
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync if (FAILED(rc)) throw rc;
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync /* this already registers the new diff image */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync rc = pParent->createDiffStorage(diff, MediumVariant_Standard,
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync pMediumLockList,
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync NULL /* aProgress */,
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync true /* aWait */,
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync NULL); // pllRegistriesThatNeedSaving
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync delete pMediumLockList;
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync if (FAILED(rc)) throw rc;
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync /* Remember created medium. */
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync pNewMedia->append(diff);
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync *ppDiff = diff;
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync }
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync catch (HRESULT rc2)
f6dd48677b626c383d1a91cba7688abb0945af7dvboxsync {
6ca8a1595bddf29de7894958ae74c255eb2693bevboxsync rc = rc2;
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync }
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync catch (...)
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync {
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync rc = VirtualBox::handleUnexpectedExceptions(RT_SRC_POS);
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync }
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync return rc;
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync}
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync
e1d4cfd32955e4e0f3499b487b46aa33cdd35ceavboxsyncvoid MachineCloneVM::destroy()
72fb956d8f85adf4ec9a4b2aa7727f57b7dcba36vboxsync{
e1d4cfd32955e4e0f3499b487b46aa33cdd35ceavboxsync delete this;
e1d4cfd32955e4e0f3499b487b46aa33cdd35ceavboxsync}
e1d4cfd32955e4e0f3499b487b46aa33cdd35ceavboxsync
e1d4cfd32955e4e0f3499b487b46aa33cdd35ceavboxsync