VirtualBox

Ignore:
Timestamp:
Oct 26, 2009 3:04:35 PM (15 years ago)
Author:
vboxsync
Message:

VBoxManage: add snapshot dump command for debugging snapshot trees.

File:
1 edited

Legend:

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

    r23882 r24081  
    2525#include <VBox/com/com.h>
    2626#include <VBox/com/string.h>
     27#include <VBox/com/array.h>
    2728#include <VBox/com/ErrorInfo.h>
    2829#include <VBox/com/errorprint.h>
     
    3637using namespace com;
    3738
     39/**
     40 * Helper function used with "VBoxManage snapshot ... dump".
     41 * @param pMedium
     42 * @param pThisSnapshot
     43 * @param pCurrentSnapshot
     44 * @param uMediumLevel
     45 * @param uSnapshotLevel
     46 * @return
     47 */
     48bool FindAndPrintSnapshotUsingMedium(ComPtr<IMedium> &pMedium,
     49                                     ComPtr<ISnapshot> &pThisSnapshot,
     50                                     ComPtr<ISnapshot> &pCurrentSnapshot,
     51                                     uint32_t uMediumLevel,
     52                                     uint32_t uSnapshotLevel)
     53{
     54    HRESULT rc;
     55
     56    do
     57    {
     58        // get snapshot machine so we can figure out which diff image this created
     59        ComPtr<IMachine> pSnapshotMachine;
     60        CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Machine)(pSnapshotMachine.asOutParam()));
     61
     62        // get media attachments
     63        SafeIfaceArray<IMediumAttachment> aAttachments;
     64        CHECK_ERROR_BREAK(pSnapshotMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aAttachments)));
     65
     66        bool fFound = false;
     67
     68        for (uint32_t i = 0;
     69             i < aAttachments.size();
     70             ++i)
     71        {
     72            ComPtr<IMediumAttachment> pAttach(aAttachments[i]);
     73            DeviceType_T type;
     74            CHECK_ERROR_BREAK(pAttach, COMGETTER(Type)(&type));
     75            if (type == DeviceType_HardDisk)
     76            {
     77                ComPtr<IMedium> pMediumInSnapshot;
     78                CHECK_ERROR_BREAK(pAttach, COMGETTER(Medium)(pMediumInSnapshot.asOutParam()));
     79
     80                if (pMediumInSnapshot == pMedium)
     81                {
     82                    // get snapshot name
     83                    Bstr bstrSnapshotName;
     84                    CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Name)(bstrSnapshotName.asOutParam()));
     85
     86                    RTPrintf("%*s  \"%ls\"\n",
     87                             50 + uSnapshotLevel * 2, "",            // indent
     88                             bstrSnapshotName.raw());
     89                    return true;        // found
     90                }
     91            }
     92        }
     93
     94        if (!fFound)
     95        {
     96            SafeIfaceArray<ISnapshot> aSnapshots;
     97            CHECK_ERROR_BREAK(pThisSnapshot, COMGETTER(Children)(ComSafeArrayAsOutParam(aSnapshots)));
     98
     99            for (uint32_t i = 0;
     100                i < aSnapshots.size();
     101                ++i)
     102            {
     103                ComPtr<ISnapshot> pChild(aSnapshots[i]);
     104                if (FindAndPrintSnapshotUsingMedium(pMedium,
     105                                                    pChild,
     106                                                    pCurrentSnapshot,
     107                                                    uMediumLevel,
     108                                                    uSnapshotLevel + 1))
     109                    // found:
     110                    break;
     111            }
     112        }
     113    } while (0);
     114
     115    return false;
     116}
     117
     118/**
     119 * Helper function used with "VBoxManage snapshot ... dump". Called from DumpSnapshot()
     120 * for each hard disk attachment found in a virtual machine. This then writes out the
     121 * root (base) medium for that hard disk attachment and recurses into the children
     122 * tree of that medium, correlating it with the snapshots of the machine.
     123 * @param pCurrentStateMedium constant, the medium listed in the current machine data (latest diff image).
     124 * @param pMedium variant, initially the base medium, then a child of the base medium when recursing.
     125 * @param pRootSnapshot constant, the root snapshot of the machine, if any; this then looks into the child snapshots.
     126 * @param pCurrentSnapshot constant, the machine's current snapshot (so we can mark it in the output).
     127 * @param uLevel variant, the recursion level for output indentation.
     128 */
     129void DumpMediumWithChildren(ComPtr<IMedium> &pCurrentStateMedium,
     130                            ComPtr<IMedium> &pMedium,
     131                            ComPtr<ISnapshot> &pRootSnapshot,
     132                            ComPtr<ISnapshot> &pCurrentSnapshot,
     133                            uint32_t uLevel)
     134{
     135    HRESULT rc;
     136    do
     137    {
     138        // print this medium
     139        Bstr bstrMediumName;
     140        CHECK_ERROR_BREAK(pMedium, COMGETTER(Name)(bstrMediumName.asOutParam()));
     141        RTPrintf("%*s  \"%ls\"%s\n",
     142                 uLevel * 2, "",            // indent
     143                 bstrMediumName.raw(),
     144                 (pCurrentStateMedium == pMedium) ? " (CURRENT STATE)" : "");
     145
     146        // find and print the snapshot that uses this particular medium (diff image)
     147        FindAndPrintSnapshotUsingMedium(pMedium, pRootSnapshot, pCurrentSnapshot, uLevel, 0);
     148
     149        // recurse into children
     150        SafeIfaceArray<IMedium> aChildren;
     151        CHECK_ERROR_BREAK(pMedium, COMGETTER(Children)(ComSafeArrayAsOutParam(aChildren)));
     152        for (uint32_t i = 0;
     153             i < aChildren.size();
     154             ++i)
     155        {
     156            ComPtr<IMedium> pChild(aChildren[i]);
     157            DumpMediumWithChildren(pCurrentStateMedium, pChild, pRootSnapshot, pCurrentSnapshot, uLevel + 1);
     158        }
     159    } while (0);
     160}
     161
     162/**
     163 * Implementation for "VBoxManage snapshot ... dump". This goes thru the machine's
     164 * medium attachments and calls DumpMediumWithChildren() for each hard disk medium found,
     165 * which then dumps the parent/child tree of that medium together with the corresponding
     166 * snapshots.
     167 * @param pMachine Machine to dump snapshots for.
     168 */
     169void DumpSnapshot(ComPtr<IMachine> &pMachine)
     170{
     171    HRESULT rc;
     172
     173    do
     174    {
     175        // get root snapshot
     176        ComPtr<ISnapshot> pSnapshot;
     177        CHECK_ERROR_BREAK(pMachine, GetSnapshot(Bstr(""), pSnapshot.asOutParam()));
     178
     179        // get current snapshot
     180        ComPtr<ISnapshot> pCurrentSnapshot;
     181        CHECK_ERROR_BREAK(pMachine, COMGETTER(CurrentSnapshot)(pCurrentSnapshot.asOutParam()));
     182
     183        // get media attachments
     184        SafeIfaceArray<IMediumAttachment> aAttachments;
     185        CHECK_ERROR_BREAK(pMachine, COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aAttachments)));
     186        for (uint32_t i = 0;
     187             i < aAttachments.size();
     188             ++i)
     189        {
     190            ComPtr<IMediumAttachment> pAttach(aAttachments[i]);
     191            DeviceType_T type;
     192            CHECK_ERROR_BREAK(pAttach, COMGETTER(Type)(&type));
     193            if (type == DeviceType_HardDisk)
     194            {
     195                ComPtr<IMedium> pCurrentStateMedium;
     196                CHECK_ERROR_BREAK(pAttach, COMGETTER(Medium)(pCurrentStateMedium.asOutParam()));
     197
     198                ComPtr<IMedium> pBaseMedium;
     199                CHECK_ERROR_BREAK(pCurrentStateMedium, COMGETTER(Base)(pBaseMedium.asOutParam()));
     200
     201                Bstr bstrBaseMediumName;
     202                CHECK_ERROR_BREAK(pBaseMedium, COMGETTER(Name)(bstrBaseMediumName.asOutParam()));
     203
     204                RTPrintf("[%RI32] Images and snapshots for medium \"%ls\"\n", i, bstrBaseMediumName.raw());
     205
     206                DumpMediumWithChildren(pCurrentStateMedium,
     207                                       pBaseMedium,
     208                                       pSnapshot,
     209                                       pCurrentSnapshot,
     210                                       0);
     211            }
     212        }
     213    } while (0);
     214}
     215
     216/**
     217 * Implementation for all VBoxManage snapshot ... subcommands.
     218 * @param a
     219 * @return
     220 */
    38221int handleSnapshot(HandlerArg *a)
    39222{
     
    45228
    46229    /* the first argument must be the VM */
    47     ComPtr<IMachine> machine;
     230    Bstr bstrMachine(a->argv[0]);
     231    ComPtr<IMachine> pMachine;
    48232    /* assume it's a UUID */
    49     rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
    50     if (FAILED(rc) || !machine)
     233    rc = a->virtualBox->GetMachine(bstrMachine, pMachine.asOutParam());
     234    if (FAILED(rc) || !pMachine)
    51235    {
    52236        /* must be a name */
    53         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
     237        CHECK_ERROR(a->virtualBox, FindMachine(bstrMachine, pMachine.asOutParam()));
    54238    }
    55     if (!machine)
     239    if (!pMachine)
    56240        return 1;
    57241    Bstr guid;
    58     machine->COMGETTER(Id)(guid.asOutParam());
     242    pMachine->COMGETTER(Id)(guid.asOutParam());
    59243
    60244    do
     
    173357            if (!guid.isEmpty())
    174358            {
    175                 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, pSnapshot.asOutParam()));
     359                CHECK_ERROR_BREAK(pMachine, GetSnapshot(guid, pSnapshot.asOutParam()));
    176360            }
    177361            else
    178362            {
    179363                /* then it must be a name */
    180                 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), pSnapshot.asOutParam()));
     364                CHECK_ERROR_BREAK(pMachine, FindSnapshot(Bstr(a->argv[2]), pSnapshot.asOutParam()));
    181365                pSnapshot->COMGETTER(Id)(guid.asOutParam());
    182366            }
     
    220404                || !strcmp(a->argv[2], "-current"))
    221405            {
    222                 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
     406                CHECK_ERROR_BREAK(pMachine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
    223407            }
    224408            else
     
    228412                if (!guid.isEmpty())
    229413                {
    230                     CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
     414                    CHECK_ERROR_BREAK(pMachine, GetSnapshot(guid, snapshot.asOutParam()));
    231415                }
    232416                else
    233417                {
    234418                    /* then it must be a name */
    235                     CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
     419                    CHECK_ERROR_BREAK(pMachine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
    236420                }
    237421            }
     
    291475            if (!guid.isEmpty())
    292476            {
    293                 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
     477                CHECK_ERROR_BREAK(pMachine, GetSnapshot(guid, snapshot.asOutParam()));
    294478            }
    295479            else
    296480            {
    297481                /* then it must be a name */
    298                 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
     482                CHECK_ERROR_BREAK(pMachine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
    299483            }
    300484
    301485            /* get the machine of the given snapshot */
    302             ComPtr<IMachine> machine;
    303             snapshot->COMGETTER(Machine)(machine.asOutParam());
    304             showVMInfo(a->virtualBox, machine, VMINFO_NONE, console);
     486            ComPtr<IMachine> pMachine2;
     487            snapshot->COMGETTER(Machine)(pMachine2.asOutParam());
     488            showVMInfo(a->virtualBox, pMachine2, VMINFO_NONE, console);
     489        }
     490        else if (!strcmp(a->argv[1], "dump"))          // undocumented parameter to debug snapshot info
     491        {
     492            DumpSnapshot(pMachine);
    305493        }
    306494        else
Note: See TracChangeset for help on using the changeset viewer.

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