VirtualBox

Ignore:
Timestamp:
May 14, 2012 2:46:29 PM (13 years ago)
Author:
vboxsync
Message:

VBoxBalloonCtrl: Added VM grouping support, update on API monitor.

Location:
trunk/src/VBox/Frontends/VBoxBalloonCtrl
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp

    r40014 r41286  
    2222*******************************************************************************/
    2323#ifndef VBOX_ONLY_DOCS
     24# include <iprt/message.h>
    2425# include <VBox/com/errorprint.h>
    2526#endif /* !VBOX_ONLY_DOCS */
     
    5354{
    5455    /** Unknown / unhandled response. */
    55     APIMON_RESPONSE_UNKNOWN    = 0,
     56    APIMON_RESPONSE_NONE       = 0,
     57    /** Does a hard power off. */
     58    APIMON_RESPONSE_POWEROFF   = 200,
     59    /** Tries to save the current machine state. */
     60    APIMON_RESPONSE_SAVE       = 250,
    5661    /** Tries to shut down all running VMs in
    5762     *  a gentle manner. */
    58     APIMON_RESPONSE_SHUTDOWN   = 200
     63    APIMON_RESPONSE_SHUTDOWN   = 300
    5964};
    6065
    61 static Bstr                         g_strAPIMonGroups;
    62 
    63 static APIMON_RESPONSE              g_enmAPIMonIslnResp     = APIMON_RESPONSE_UNKNOWN;
     66/** The VM group(s) the API monitor handles. If none, all VMs get handled. */
     67static mapGroups                    g_vecAPIMonGroups;
     68static APIMON_RESPONSE              g_enmAPIMonIslnResp     = APIMON_RESPONSE_NONE;
    6469static unsigned long                g_ulAPIMonIslnTimeoutMS = 0;
    6570static Bstr                         g_strAPIMonIslnLastBeat;
    6671static uint64_t                     g_uAPIMonIslnLastBeatMS = 0;
    6772
    68 int apimonResponseToEnum(const char *pszResponse, APIMON_RESPONSE *pResp)
     73static int apimonResponseToEnum(const char *pszResponse, APIMON_RESPONSE *pResp)
    6974{
    7075    AssertPtrReturn(pszResponse, VERR_INVALID_POINTER);
     
    7277
    7378    int rc = VINF_SUCCESS;
    74     if (   !RTStrICmp(pszResponse, "shutdown")
    75         || !RTStrICmp(pszResponse, "poweroff"))
     79    if (   !RTStrICmp(pszResponse, "poweroff")
     80        || !RTStrICmp(pszResponse, "powerdown"))
     81    {
     82        *pResp = APIMON_RESPONSE_POWEROFF;
     83    }
     84    else if (   !RTStrICmp(pszResponse, "shutdown")
     85             || !RTStrICmp(pszResponse, "shutoff"))
    7686    {
    7787        *pResp = APIMON_RESPONSE_SHUTDOWN;
    7888    }
     89    else if (!RTStrICmp(pszResponse, "save"))
     90    {
     91        *pResp = APIMON_RESPONSE_SAVE;
     92    }
    7993    else
    80         *pResp = APIMON_RESPONSE_UNKNOWN;
    81 
    82     return (*pResp > APIMON_RESPONSE_UNKNOWN ? VINF_SUCCESS : VERR_INVALID_PARAMETER);
    83 }
    84 
    85 int apimonMachineControl(const Bstr &strUuid, PVBOXWATCHDOG_MACHINE pMachine,
    86                          APIMON_RESPONSE enmResp)
     94    {
     95        *pResp = APIMON_RESPONSE_NONE;
     96        rc = VERR_INVALID_PARAMETER;
     97    }
     98
     99    return rc;
     100}
     101
     102static const char* apimonResponseToStr(APIMON_RESPONSE enmResp)
     103{
     104    if (APIMON_RESPONSE_POWEROFF == enmResp)
     105        return "powering off";
     106    else if (APIMON_RESPONSE_SHUTDOWN == enmResp)
     107        return "shutting down";
     108    else if (APIMON_RESPONSE_SAVE == enmResp)
     109        return "saving state";
     110    else if (APIMON_RESPONSE_NONE == enmResp)
     111        return "none";
     112
     113    return "unknown";
     114}
     115
     116/* Copied from VBoxManageInfo.cpp. */
     117static const char *apimonMachineStateToName(MachineState_T machineState, bool fShort)
     118{
     119    switch (machineState)
     120    {
     121        case MachineState_PoweredOff:
     122            return fShort ? "poweroff"             : "powered off";
     123        case MachineState_Saved:
     124            return "saved";
     125        case MachineState_Aborted:
     126            return "aborted";
     127        case MachineState_Teleported:
     128            return "teleported";
     129        case MachineState_Running:
     130            return "running";
     131        case MachineState_Paused:
     132            return "paused";
     133        case MachineState_Stuck:
     134            return fShort ? "gurumeditation"       : "guru meditation";
     135        case MachineState_LiveSnapshotting:
     136            return fShort ? "livesnapshotting"     : "live snapshotting";
     137        case MachineState_Teleporting:
     138            return "teleporting";
     139        case MachineState_Starting:
     140            return "starting";
     141        case MachineState_Stopping:
     142            return "stopping";
     143        case MachineState_Saving:
     144            return "saving";
     145        case MachineState_Restoring:
     146            return "restoring";
     147        case MachineState_TeleportingPausedVM:
     148            return fShort ? "teleportingpausedvm"  : "teleporting paused vm";
     149        case MachineState_TeleportingIn:
     150            return fShort ? "teleportingin"        : "teleporting (incoming)";
     151        case MachineState_RestoringSnapshot:
     152            return fShort ? "restoringsnapshot"    : "restoring snapshot";
     153        case MachineState_DeletingSnapshot:
     154            return fShort ? "deletingsnapshot"     : "deleting snapshot";
     155        case MachineState_DeletingSnapshotOnline:
     156            return fShort ? "deletingsnapshotlive" : "deleting snapshot live";
     157        case MachineState_DeletingSnapshotPaused:
     158            return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";
     159        case MachineState_SettingUp:
     160            return fShort ? "settingup"           : "setting up";
     161        default:
     162            break;
     163    }
     164    return "unknown";
     165}
     166
     167static int apimonMachineControl(const Bstr &strUuid, PVBOXWATCHDOG_MACHINE pMachine,
     168                                APIMON_RESPONSE enmResp, unsigned long ulTimeout)
    87169{
    88170    /** @todo Add other commands (with enmResp) here. */
    89     AssertPtrReturn(pMachine, VERR_INVALID_PARAMETER);
    90 
    91     serviceLog("Shutting down machine \"%ls\"\n", strUuid.raw());
     171    AssertPtrReturn(pMachine, VERR_INVALID_POINTER);
     172
     173    serviceLogVerbose(("apimon: Triggering \"%s\" (%RU32ms timeout) for machine \"%ls\"\n",
     174                      apimonResponseToStr(enmResp), ulTimeout, strUuid.raw()));
     175
     176    if (   enmResp == APIMON_RESPONSE_NONE
     177        || g_fDryrun)
     178        return VINF_SUCCESS; /* Nothing to do. */
     179
     180    HRESULT rc;
     181    ComPtr <IMachine> machine;
     182    CHECK_ERROR_RET(g_pVirtualBox, FindMachine(strUuid.raw(),
     183                                               machine.asOutParam()), VERR_NOT_FOUND);
    92184
    93185    /* Open a session for the VM. */
    94     HRESULT rc;
    95     CHECK_ERROR_RET(pMachine->machine, LockMachine(g_pSession, LockType_Shared), VERR_ACCESS_DENIED);
     186    CHECK_ERROR_RET(machine, LockMachine(g_pSession, LockType_Shared), VERR_ACCESS_DENIED);
     187
    96188    do
    97189    {
    98         /* get the associated console */
     190
     191        /* Get the associated console. */
    99192        ComPtr<IConsole> console;
    100193        CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam()));
    101194
    102         if (!g_fDryrun)
     195        /* Query the machine's state to avoid unnecessary IPC. */
     196        MachineState_T machineState;
     197        CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
     198        if (   machineState == MachineState_Running
     199            || machineState == MachineState_Paused)
    103200        {
    104201            ComPtr<IProgress> progress;
    105             CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
    106             if (g_fVerbose)
     202
     203            switch (enmResp)
    107204            {
    108                 serviceLogVerbose(("Waiting for shutting down machine \"%ls\" ...\n",
    109                                    strUuid.raw()));
    110                 progress->WaitForCompletion(-1);
     205                case APIMON_RESPONSE_POWEROFF:
     206                    CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
     207                    serviceLogVerbose(("apimon: Waiting for powering off machine \"%ls\" ...\n",
     208                                       strUuid.raw()));
     209                    progress->WaitForCompletion(ulTimeout);
     210                    CHECK_PROGRESS_ERROR(progress, ("Failed to power off machine \"%ls\"",
     211                                         strUuid.raw()));
     212                    break;
     213
     214                case APIMON_RESPONSE_SAVE:
     215                {
     216                    /* First pause so we don't trigger a live save which needs more time/resources. */
     217                    bool fPaused = false;
     218                    rc = console->Pause();
     219                    if (FAILED(rc))
     220                    {
     221                        bool fError = true;
     222                        if (rc == VBOX_E_INVALID_VM_STATE)
     223                        {
     224                            /* Check if we are already paused. */
     225                            MachineState_T machineState;
     226                            CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
     227                            /* The error code was lost by the previous instruction. */
     228                            rc = VBOX_E_INVALID_VM_STATE;
     229                            if (machineState != MachineState_Paused)
     230                            {
     231                                serviceLog("apimon: Machine \"%s\" in invalid state %d -- %s\n",
     232                                           strUuid.raw(), machineState, apimonMachineStateToName(machineState, false));
     233                            }
     234                            else
     235                            {
     236                                fError = false;
     237                                fPaused = true;
     238                            }
     239                        }
     240                        if (fError)
     241                            break;
     242                    }
     243
     244                    serviceLogVerbose(("apimon: Waiting for saving state of machine \"%ls\" ...\n",
     245                                       strUuid.raw()));
     246
     247                    ComPtr<IProgress> progress;
     248                    CHECK_ERROR(console, SaveState(progress.asOutParam()));
     249                    if (FAILED(rc))
     250                    {
     251                        if (!fPaused)
     252                            console->Resume();
     253                        break;
     254                    }
     255
     256                    progress->WaitForCompletion(ulTimeout);
     257                    CHECK_PROGRESS_ERROR(progress, ("Failed to save machine state of machine \"%ls\"",
     258                                         strUuid.raw()));
     259                    if (FAILED(rc))
     260                    {
     261                        if (!fPaused)
     262                            console->Resume();
     263                    }
     264
     265                    break;
     266                }
     267
     268                case APIMON_RESPONSE_SHUTDOWN:
     269                    CHECK_ERROR_BREAK(console, PowerButton());
     270                    serviceLogVerbose(("apimon: Waiting for shutdown of machine \"%ls\" ...\n",
     271                                       strUuid.raw()));
     272                    progress->WaitForCompletion(ulTimeout);
     273                    CHECK_PROGRESS_ERROR(progress, ("Failed to shutdown machine \"%ls\"",
     274                                         strUuid.raw()));
     275                    break;
     276
     277                default:
     278                    AssertMsgFailed(("Response %d not implemented", enmResp));
     279                    break;
    111280            }
    112281        }
     282        else
     283            serviceLog("apimon: Machine \"%s\" is in invalid state \"%s\" (%d) for triggering \"%s\"\n",
     284                       strUuid.raw(), apimonMachineStateToName(machineState, false), machineState,
     285                       apimonResponseToStr(enmResp));
    113286    } while (0);
    114287
     
    119292}
    120293
    121 int apimonTrigger(APIMON_RESPONSE enmResp)
     294static bool apimonHandleVM(const PVBOXWATCHDOG_MACHINE pMachine)
     295{
     296    bool fHandleVM = false;
     297
     298    try
     299    {
     300        mapGroupsIterConst itVMGroup = pMachine->groups.begin();
     301        while (   itVMGroup != pMachine->groups.end()
     302               && !fHandleVM)
     303        {
     304            mapGroupsIterConst itInGroup = g_vecAPIMonGroups.find(itVMGroup->first);
     305            if (itInGroup != g_vecAPIMonGroups.end())
     306                fHandleVM = true;
     307
     308            itVMGroup++;
     309        }
     310    }
     311    catch (...)
     312    {
     313        AssertFailed();
     314    }
     315
     316    return fHandleVM;
     317}
     318
     319static int apimonTrigger(APIMON_RESPONSE enmResp)
    122320{
    123321    int rc = VINF_SUCCESS;
    124322
    125     /** @todo Add proper grouping support! */
    126     bool fAllGroups = g_strAPIMonGroups.isEmpty();
     323    bool fAllGroups = g_vecAPIMonGroups.empty();
    127324    mapVMIter it = g_mapVM.begin();
     325
     326    if (it == g_mapVM.end())
     327    {
     328        serviceLog("apimon: No machines in list, skipping ...\n");
     329        return rc;
     330    }
     331
    128332    while (it != g_mapVM.end())
    129333    {
    130         if (   !it->second.group.compare(g_strAPIMonGroups, Bstr::CaseInsensitive)
    131             || fAllGroups)
    132         {
    133             rc = apimonMachineControl(it->first /* Uuid */,
    134                                        &it->second, enmResp);
    135         }
     334        bool fHandleVM = fAllGroups;
     335        try
     336        {
     337            if (!fHandleVM)
     338                fHandleVM = apimonHandleVM(&it->second);
     339
     340            if (fHandleVM)
     341            {
     342                int rc2 = apimonMachineControl(it->first /* Uuid */,
     343                                               &it->second /* Machine */, enmResp, 30 * 1000 /* 30s timeout */);
     344                if (RT_FAILURE(rc2))
     345                    serviceLog("apimon: Controlling machine \"%ls\" (action: %s) failed with rc=%Rrc",
     346                               it->first.raw(), apimonResponseToStr(enmResp), rc);
     347
     348                if (RT_SUCCESS(rc))
     349                    rc = rc2; /* Store original error. */
     350                /* Keep going. */
     351            }
     352        }
     353        catch (...)
     354        {
     355            AssertFailed();
     356        }
     357
    136358        it++;
    137359    }
     
    176398            case GETOPTDEF_APIMON_ISLN_TIMEOUT:
    177399                g_ulAPIMonIslnTimeoutMS = ValueUnion.u32;
    178                 if (g_ulAPIMonIslnTimeoutMS < 1000)
     400                if (g_ulAPIMonIslnTimeoutMS < 1000) /* Don't allow timeouts < 1s. */
    179401                    g_ulAPIMonIslnTimeoutMS = 1000;
    180402                break;
    181403
    182404            case GETOPTDEF_APIMON_GROUPS:
    183                 g_strAPIMonGroups = ValueUnion.psz;
     405            {
     406                rc = groupAdd(g_vecAPIMonGroups, ValueUnion.psz, 0 /* Flags */);
     407                if (RT_FAILURE(rc))
     408                    rc = -1; /* Option unknown. */
    184409                break;
     410            }
    185411
    186412            default:
     
    211437        if (!g_ulAPIMonIslnTimeoutMS) /* Still not set? Use a default. */
    212438        {
    213             serviceLogVerbose(("API monitor isolation timeout not given, defaulting to 30s\n"));
     439            serviceLogVerbose(("apimon: API monitor isolation timeout not given, defaulting to 30s\n"));
    214440
    215441            /* Default is 30 seconds timeout. */
     
    218444
    219445        /* VM groups to watch for. */
    220         if (g_strAPIMonGroups.isEmpty()) /* Not set by command line? */
     446        if (g_vecAPIMonGroups.empty()) /* Not set by command line? */
    221447        {
    222448            CHECK_ERROR_BREAK(g_pVirtualBox, GetExtraData(Bstr("Watchdog/APIMonitor/Groups").raw(),
    223                                                           g_strAPIMonGroups.asOutParam()));
     449                                                          strValue.asOutParam()));
     450            if (!strValue.isEmpty())
     451            {
     452                int rc2 = groupAdd(g_vecAPIMonGroups, Utf8Str(strValue).c_str(), 0 /* Flags */);
     453                if (RT_FAILURE(rc2))
     454                    serviceLog("apimon: Warning: API monitor groups string invalid (%ls)\n", strValue.raw());
     455            }
    224456        }
    225457
    226458        /* Host isolation command response. */
    227         if (g_enmAPIMonIslnResp == APIMON_RESPONSE_UNKNOWN) /* Not set by command line? */
     459        if (g_enmAPIMonIslnResp == APIMON_RESPONSE_NONE) /* Not set by command line? */
    228460        {
    229461            CHECK_ERROR_BREAK(g_pVirtualBox, GetExtraData(Bstr("Watchdog/APIMonitor/IsolationResponse").raw(),
     
    233465                int rc2 = apimonResponseToEnum(Utf8Str(strValue).c_str(), &g_enmAPIMonIslnResp);
    234466                if (RT_FAILURE(rc2))
    235                 {
    236                     serviceLog("Warning: API monitor response string invalid (%ls), default to shutdown\n",
     467                    serviceLog("apimon: Warning: API monitor response string invalid (%ls), defaulting to no action\n",
    237468                               strValue.raw());
    238                     g_enmAPIMonIslnResp = APIMON_RESPONSE_SHUTDOWN;
    239                 }
    240469            }
    241             else
    242                 g_enmAPIMonIslnResp = APIMON_RESPONSE_SHUTDOWN;
    243470        }
    244471    } while (0);
     
    257484    uint64_t uNow = RTTimeProgramMilliTS();
    258485    uint64_t uDelta = uNow - uLastRun;
    259     if (uDelta < 1000)
     486    if (uDelta < 1000) /* Only check every second (or later). */
    260487        return VINF_SUCCESS;
    261488    uLastRun = uNow;
     
    264491    HRESULT rc;
    265492
    266     serviceLogVerbose(("Checking for API heartbeat (%RU64ms) ...\n",
     493#ifdef DEBUG
     494    serviceLogVerbose(("apimon: Checking for API heartbeat (%RU64ms) ...\n",
    267495                       g_ulAPIMonIslnTimeoutMS));
     496#endif
    268497
    269498    do
     
    276505            && g_strAPIMonIslnLastBeat.compare(strHeartbeat, Bstr::CaseSensitive))
    277506        {
    278             serviceLogVerbose(("API heartbeat received, resetting timeout\n"));
     507            serviceLogVerbose(("apimon: API heartbeat received, resetting timeout\n"));
    279508
    280509            g_uAPIMonIslnLastBeatMS = 0;
     
    286515            if (g_uAPIMonIslnLastBeatMS > g_ulAPIMonIslnTimeoutMS)
    287516            {
    288                 serviceLogVerbose(("No API heartbeat within time received (%RU64ms)\n",
     517                serviceLogVerbose(("apimon: No API heartbeat within time received (%RU64ms)\n",
    289518                                   g_ulAPIMonIslnTimeoutMS));
    290519
     
    329558{
    330559    if (!fAvailable)
    331         apimonTrigger(g_enmAPIMonIslnResp);
     560    {
     561        serviceLog(("apimon: VBoxSVC became unavailable, triggering action\n"));
     562        return apimonTrigger(g_enmAPIMonIslnResp);
     563    }
    332564    return VINF_SUCCESS;
    333565}
  • trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModBallooning.cpp

    r40011 r41286  
    205205    /* Only do ballooning if we have a maximum balloon size set. */
    206206    PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD pData = (PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD)
    207                                               getPayload(pMachine, VBOX_MOD_BALLOONING_NAME);
     207                                              payloadFrom(pMachine, VBOX_MOD_BALLOONING_NAME);
    208208    AssertPtr(pData);
    209209    pData->ulBalloonSizeMax = pMachine->machine.isNull()
     
    298298
    299299        PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD pData = (PVBOXWATCHDOG_BALLOONCTRL_PAYLOAD)
    300                                                   getPayload(pMachine, VBOX_MOD_BALLOONING_NAME);
     300                                                  payloadFrom(pMachine, VBOX_MOD_BALLOONING_NAME);
    301301        AssertPtr(pData);
    302302
     
    316316                       lDelta > 0 ? "Inflating" : "Deflating", lDelta, lBalloonCur);
    317317
    318             HRESULT rc;
    319 
    320318            if (!g_fDryrun)
    321319            {
    322320                /* Open a session for the VM. */
     321                HRESULT rc;
    323322                CHECK_ERROR(pMachine->machine, LockMachine(g_pSession, LockType_Shared));
    324323
     
    336335                        serviceLog("Error: Unable to set new balloon size %ld for machine \"%ls\", rc=%Rhrc",
    337336                                   lBalloonCur, strUuid.raw(), rc);
     337                    if (FAILED(rc))
     338                        vrc = VERR_COM_IPRT_ERROR;
    338339                } while (0);
    339340
  • trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdog.cpp

    r41100 r41286  
    137137static int machineAdd(const Bstr &strUuid);
    138138static int machineRemove(const Bstr &strUuid);
    139 static HRESULT watchdogSetup();
     139static int watchdogSetup();
    140140static void watchdogShutdown();
    141141
     
    264264                    {
    265265                        serviceLog("VBoxSVC became available\n");
    266                         HRESULT hrc = watchdogSetup();
    267                         if (FAILED(hrc))
    268                             serviceLog("Unable to re-set up watchdog (rc=%Rhrc)!\n", hrc);
     266                        int rc2 = watchdogSetup();
     267                        if (RT_FAILURE(rc2))
     268                            serviceLog("Unable to re-set up watchdog (rc=%Rrc)!\n", rc2);
    269269                    }
    270270
     
    347347        Assert(!machine.isNull());
    348348
    349         Bstr strGroup;
     349        /* Note: Currently only one group per VM supported? We don't care. */
     350        Bstr strGroups;
    350351        CHECK_ERROR_BREAK(machine, GetExtraData(Bstr("VBoxInternal2/VMGroup").raw(),
    351                                                 strGroup.asOutParam()));
     352                                                strGroups.asOutParam()));
    352353
    353354        /*
     
    356357        VBOXWATCHDOG_MACHINE m;
    357358        m.machine = machine;
    358         m.group = strGroup;
     359        int rc2 = groupAdd(m.groups, Utf8Str(strGroups).c_str(), 0 /* Flags */);
     360        AssertRC(rc2);
    359361
    360362        mapVMIter it = g_mapVM.find(strUuid);
     
    366368         * Get the machine's VM group(s).
    367369         */
    368         if (!strGroup.isEmpty())
    369         {
    370             serviceLogVerbose(("Machine \"%ls\" is in VM group \"%ls\"\n",
    371                                strUuid.raw(), strGroup.raw()));
    372 
    373             /** @todo Support more than one group! */
     370        mapGroupsIterConst itGroup = m.groups.begin();
     371        while (itGroup != m.groups.end())
     372        {
     373            serviceLogVerbose(("Machine \"%ls\" is in VM group \"%s\"\n",
     374                               strUuid.raw(), itGroup->first.c_str()));
     375
    374376            /* Add machine to group(s). */
    375             mapGroupIter itGroup = g_mapGroup.find(strGroup);
    376             if (itGroup == g_mapGroup.end())
     377            mapGroupIter itGroups = g_mapGroup.find(itGroup->first);
     378            if (itGroups == g_mapGroup.end())
    377379            {
    378380                vecGroupMembers vecMembers;
    379381                vecMembers.push_back(strUuid);
    380                 g_mapGroup.insert(std::make_pair(strGroup, vecMembers));
    381 
    382                 itGroup = g_mapGroup.find(strGroup);
    383                 Assert(itGroup != g_mapGroup.end());
     382                g_mapGroup.insert(std::make_pair(itGroup->first, vecMembers));
     383
     384                itGroups = g_mapGroup.find(itGroup->first);
     385                Assert(itGroups != g_mapGroup.end());
    384386            }
    385387            else
    386                 itGroup->second.push_back(strUuid);
     388                itGroups->second.push_back(strUuid);
    387389            serviceLogVerbose(("Group \"%ls\" now has %ld machine(s)\n",
    388                                strGroup.raw(), itGroup->second.size()));
    389         }
    390         else
    391             serviceLogVerbose(("Machine \"%ls\" has no VM group assigned\n",
    392                                strUuid.raw()));
     390                               itGroup->first.c_str(), itGroups->second.size()));
     391            itGroup++;
     392        }
    393393
    394394        /*
     
    432432    serviceLogVerbose(("Removing machine \"%ls\"\n", strUuid.raw()));
    433433
    434     mapVMIter itVM = g_mapVM.find(strUuid);
    435     Assert(itVM != g_mapVM.end());
    436 
    437     /* Remove machine from group(s). */
    438     /** @todo Add support for multiple groups! */
    439     Bstr strGroup = itVM->second.group;
    440     if (!strGroup.isEmpty())
    441     {
    442         mapGroupIter itGroup = g_mapGroup.find(strGroup);
    443         Assert(itGroup != g_mapGroup.end());
    444 
    445         vecGroupMembers vecMembers = itGroup->second;
    446         vecGroupMembersIter itMember = std::find(vecMembers.begin(),
    447                                                  vecMembers.end(),
    448                                                  strUuid);
    449         Assert(itMember != vecMembers.end());
    450         vecMembers.erase(itMember);
    451 
    452         serviceLogVerbose(("Group \"%ls\" has %ld machines left\n",
    453                            itGroup->first.raw(), vecMembers.size()));
    454         if (!vecMembers.size())
    455             g_mapGroup.erase(itGroup);
    456     }
     434    try
     435    {
     436        mapVMIter itVM = g_mapVM.find(strUuid);
     437        Assert(itVM != g_mapVM.end());
     438
     439        /* Remove machine from group(s). */
     440        mapGroupsIterConst itGroups = itVM->second.groups.begin();
     441        while (itGroups != itVM->second.groups.end())
     442        {
     443            mapGroupIter itGroup = g_mapGroup.find(itGroups->first);
     444            Assert(itGroup != g_mapGroup.end());
     445
     446            vecGroupMembers vecMembers = itGroup->second;
     447            vecGroupMembersIter itMember = std::find(vecMembers.begin(),
     448                                                     vecMembers.end(),
     449                                                     strUuid);
     450            Assert(itMember != vecMembers.end());
     451            vecMembers.erase(itMember);
     452
     453            serviceLogVerbose(("Group \"%s\" has %ld machines left\n",
     454                               itGroup->first.c_str(), vecMembers.size()));
     455            if (!vecMembers.size())
     456            {
     457                serviceLogVerbose(("Deleteting group \"%s\n", itGroup->first.c_str()));
     458                g_mapGroup.erase(itGroup);
     459            }
     460
     461            itGroups++;
     462        }
    457463
    458464#ifndef VBOX_WATCHDOG_GLOBAL_PERFCOL
    459     itVM->second.collector.setNull();
     465        itVM->second.collector.setNull();
    460466#endif
    461     itVM->second.machine.setNull();
    462 
    463     /*
    464      * Remove machine from map.
    465      */
    466     g_mapVM.erase(itVM);
     467        itVM->second.machine.setNull();
     468
     469        /*
     470         * Remove machine from map.
     471         */
     472        g_mapVM.erase(itVM);
     473    }
     474    catch (...)
     475    {
     476        AssertFailed();
     477    }
    467478
    468479    return rc;
     
    880891 * @return  HRESULT
    881892 */
    882 static HRESULT watchdogSetup()
     893static int watchdogSetup()
    883894{
    884895    serviceLogVerbose(("Setting up ...\n"));
    885896
     897    /*
     898     * Setup VirtualBox + session interfaces.
     899     */
    886900    HRESULT rc = g_pVirtualBoxClient->COMGETTER(VirtualBox)(g_pVirtualBox.asOutParam());
    887     if (FAILED(rc))
    888     {
    889         RTMsgError("Failed to get VirtualBox object (rc=%Rhrc)!", rc);
    890     }
    891     else
     901    if (SUCCEEDED(rc))
    892902    {
    893903        rc = g_pSession.createInprocObject(CLSID_Session);
     
    895905            RTMsgError("Failed to create a session object (rc=%Rhrc)!", rc);
    896906    }
    897 
    898     do
    899     {
    900         /*
    901          * Setup metrics.
    902          */
     907    else
     908        RTMsgError("Failed to get VirtualBox object (rc=%Rhrc)!", rc);
     909
     910    if (FAILED(rc))
     911        return VERR_COM_OBJECT_NOT_FOUND;
     912
     913    /*
     914     * Setup metrics.
     915     */
    903916#ifdef VBOX_WATCHDOG_GLOBAL_PERFCOL
    904         CHECK_ERROR_BREAK(g_pVirtualBox, COMGETTER(PerformanceCollector)(g_pPerfCollector.asOutParam()));
     917    CHECK_ERROR_RET(g_pVirtualBox,
     918                    COMGETTER(PerformanceCollector)(g_pPerfCollector.asOutParam()), VERR_COM_UNEXPECTED);
    905919#endif
    906920
    907         int vrc = RTCritSectInit(&g_csMachines);
    908         if (RT_FAILURE(vrc))
    909         {
    910             rc = VBOX_E_IPRT_ERROR;
    911             break;
    912         }
     921    int vrc = RTCritSectInit(&g_csMachines);
     922    if (RT_SUCCESS(vrc))
     923    {
    913924
    914925        /*
     
    916927         */
    917928        vrc = vmListBuild();
    918         if (RT_FAILURE(vrc))
    919         {
    920             rc = VBOX_E_IPRT_ERROR;
    921             break;
    922         }
    923 
    924     } while (0);
    925 
    926     return rc;
     929    }
     930
     931    return vrc;
    927932}
    928933
     
    10731078        if (RT_FAILURE(rc))
    10741079            return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to daemonize, rc=%Rrc. exiting.", rc);
    1075 
    10761080        /* create release logger, to file */
    10771081        rc = com::VBoxLogRelCreate("Watchdog", pszLogFile,
     
    10831087        if (RT_FAILURE(rc))
    10841088            return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, rc);
     1089        AssertPtr(pLoggerReleaseFile);
    10851090    }
    10861091#endif
     
    11221127        serviceLog("Running in dryrun mode\n");
    11231128
    1124     hrc = watchdogSetup();
    1125     if (FAILED(hrc))
     1129    rc = watchdogSetup();
     1130    if (RT_FAILURE(rc))
    11261131        return RTEXITCODE_FAILURE;
    11271132
  • trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogInternal.h

    r40877 r41286  
    3232#endif /* !VBOX_ONLY_DOCS */
    3333
     34#include <algorithm>
    3435#include <map>
     36#include <sstream>
     37#include <string>
    3538#include <vector>
    3639
     
    7477typedef std::map<const char*, VBOXWATCHDOG_MODULE_PAYLOAD>::const_iterator mapPayloadIterConst;
    7578
    76 struct VBOXWATCHDOG_VM_GROUP;
     79/** Group list (plus additional per-group flags, not used yet) for one VM.
     80 *  Primary key is the group name, secondary specify flags (if any). */
     81typedef std::map<Utf8Str, uint32_t> mapGroups;
     82typedef std::map<Utf8Str, uint32_t>::iterator mapGroupsIter;
     83typedef std::map<Utf8Str, uint32_t>::const_iterator mapGroupsIterConst;
    7784
    7885/** A machine's internal entry.
     
    8491    ComPtr<IPerformanceCollector> collector;
    8592#endif
    86     /** The machine's VM group(s). */
    87     Bstr group;
     93    /** The VM group(s) this machine belongs to.
     94     *  Contains groups from per-machine "VBoxInternal2/VMGroup". */
     95    mapGroups groups;
    8896    /** Map containing the individual
    8997     *  module payloads. */
     
    94102typedef std::map<Bstr, VBOXWATCHDOG_MACHINE>::const_iterator mapVMIterConst;
    95103
    96 /** Members of a VM group; currently only represented by the machine's UUID. */
     104/** Members of a VM group; currently only represented by the machine's UUID.
     105 *  Primary key is the machine's UUID. */
    97106typedef std::vector<Bstr> vecGroupMembers;
    98107typedef std::vector<Bstr>::iterator vecGroupMembersIter;
    99108typedef std::vector<Bstr>::const_iterator vecGroupMembersIterConst;
    100109
    101 /** A VM group. Can contain none, one or more group members. */
    102 typedef std::map<Bstr, vecGroupMembers> mapGroup;
    103 typedef std::map<Bstr, vecGroupMembers>::iterator mapGroupIter;
    104 typedef std::map<Bstr, vecGroupMembers>::const_iterator mapGroupIterConst;
     110/** A VM group. Can contain none, one or more group members.
     111 *  Primary key is the group's name. */
     112typedef std::map<Utf8Str, vecGroupMembers> mapGroup;
     113typedef std::map<Utf8Str, vecGroupMembers>::iterator mapGroupIter;
     114typedef std::map<Utf8Str, vecGroupMembers>::const_iterator mapGroupIterConst;
    105115
    106116/**
     
    216226#define serviceLogVerbose(a) if (g_fVerbose) { serviceLog a; }
    217227
     228int groupAdd(mapGroups &groups, const char *pszGroupsToAdd, uint32_t fFlags);
     229
    218230extern int getMetric(PVBOXWATCHDOG_MACHINE pMachine, const Bstr& strName, LONG *pulData);
    219 void* getPayload(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule);
     231void* payloadFrom(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule);
    220232int payloadAlloc(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule, size_t cbSize, void **ppszPayload);
    221233void payloadFree(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule);
  • trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxWatchdogUtils.cpp

    r39986 r41286  
    2323#include "VBoxWatchdogInternal.h"
    2424
     25
     26/**
     27 * Adds a group / a set of groups to the specified map.
     28 * If a group in the group map exists there will be no action.
     29 *
     30 * @return  IPRT status code.
     31 * @param   groups                  Map to add group(s) to.
     32 * @param   pszGroupsToAdd          Comma-separated string of one or more groups to add.
     33 * @param   fFlags                  Flags to set to the groups added.
     34 */
     35int groupAdd(mapGroups &groups, const char *pszGroupsToAdd, uint32_t fFlags)
     36{
     37    AssertPtrReturn(pszGroupsToAdd, VERR_INVALID_POINTER);
     38
     39    try
     40    {
     41        std::istringstream strGroups(pszGroupsToAdd);
     42        for(std::string strToken; getline(strGroups, strToken, ','); )
     43        {
     44            strToken.erase(remove_if(strToken.begin(), strToken.end(), isspace), strToken.end());
     45
     46            Utf8Str strTokenUtf8(strToken.c_str());
     47            mapGroupsIterConst it = groups.find(strTokenUtf8);
     48
     49            if (it == groups.end())
     50                groups.insert(std::make_pair(strTokenUtf8, fFlags));
     51        }
     52    }
     53    catch (...)
     54    {
     55        AssertFailed();
     56    }
     57
     58    return VINF_SUCCESS;
     59}
    2560
    2661/**
     
    105140 * @param   pszModule               Module name to get payload from.
    106141 */
    107 void* getPayload(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule)
     142void* payloadFrom(PVBOXWATCHDOG_MACHINE pMachine, const char *pszModule)
    108143{
    109144    AssertPtrReturn(pMachine, NULL);
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