VirtualBox

Changeset 68917 in vbox


Ignore:
Timestamp:
Sep 28, 2017 4:09:25 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
118180
Message:

main/ovfreader: Ignore invalid InstanceID on Items where it doesn't matter. Fixes problem importing OVA containing placeholder string instead of number for the 'Memory' item. bugref:8997 Also fixed bogus EthernetPortItem and StorageItem object handling, instances would always be stripped down to VirtualHardwareItem after parsing and checking. Cleaned up the item parsing, reducing code duplication. Also reduced the excessive object copying during parsing a little.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/ovfreader.h

    r65066 r68917  
    2323#include "iprt/cpp/xml.h"
    2424#include <map>
     25#include <vector>
    2526
    2627namespace ovf
     
    492493struct VirtualSystem;
    493494
    494 typedef std::map<uint32_t, VirtualHardwareItem> HardwareItemsMap;
     495
     496/**
     497 * VirtualHardwareItem pointer vector with safe cleanup.
     498 *
     499 * We need to use object pointers because we also want EthernetPortItem and
     500 * StorageItems to go into the container.
     501 */
     502class HardwareItemVector : public std::vector<VirtualHardwareItem *>
     503{
     504public:
     505    HardwareItemVector() : std::vector<VirtualHardwareItem *>() { }
     506    ~HardwareItemVector()
     507    {
     508        for (iterator it = begin(); it != end(); ++it)
     509            delete(*it);
     510        clear();
     511    }
     512
     513    /* There is no copying of this vector.  We'd need something like shared_ptr for that. */
     514private:
     515    HardwareItemVector(const VirtualSystem &);
     516
     517};
    495518
    496519struct HardDiskController
     
    564587                                                // VMware Workstation 6.5 is "vmx-07"
    565588
    566     HardwareItemsMap    mapHardwareItems;       // map of virtual hardware items, sorted by unique instance ID
     589    HardwareItemVector  vecHardwareItems;       //< vector containing all virtual hardware items in parsing order.
    567590
    568591    uint64_t            ullMemorySize;          // always in bytes, copied from llHardwareItems; default = 0 (unspecified)
  • trunk/src/VBox/Main/xml/ovfreader.cpp

    r65088 r68917  
    1818 */
    1919
     20#define LOG_GROUP LOG_GROUP_MAIN_APPLIANCE
    2021#include "ovfreader.h"
     22#include <VBox/log.h>
     23#include <vector>
    2124
    2225using namespace std;
    2326using namespace ovf;
     27
     28
    2429
    2530////////////////////////////////////////////////////////////////////////////////
     
    325330void OVFReader::HandleVirtualSystemContent(const xml::ElementNode *pelmVirtualSystem)
    326331{
    327     VirtualSystem vsys;
     332    /* Create a new virtual system and work directly on the list copy. */
     333    m_llVirtualSystems.push_back(VirtualSystem());
     334    VirtualSystem &vsys = m_llVirtualSystems.back();
    328335
    329336    // peek under the <VirtualSystem> node whether we have a <vbox:Machine> node;
     
    412419            }
    413420
     421            /* Parse the items into the hardware item vector. */
    414422            {
    415                 xml::NodesLoop loopVirtualHardwareItems(*pelmThis, "Item");      // all "Item" child elements
     423                std::map<uint32_t, const VirtualHardwareItem *> mapHardwareItems;
     424                xml::NodesLoop childrenIterator(*pelmThis);
    416425                const xml::ElementNode *pelmItem;
    417                 while ((pelmItem = loopVirtualHardwareItems.forAllNodes()))
     426                while ((pelmItem = childrenIterator.forAllNodes()) != NULL)
    418427                {
    419                     VirtualHardwareItem i;
    420 
    421                     i.ulLineNumber = pelmItem->getLineNumber();
    422                     i.fillItem(pelmItem);
    423                     try{
    424                         i.checkConsistencyAndCompliance();
     428                    /* Parse according to type. */
     429                    VirtualHardwareItem *pItem;
     430                    const char *pszName = pelmItem->getName();
     431                    if (RTStrCmp(pszName, "Item") == 0)
     432                        pItem = new VirtualHardwareItem();
     433                    else if (RTStrCmp(pszName, "StorageItem") == 0)
     434                        pItem = new StorageItem();
     435                    else if (RTStrCmp(pszName, "EthernetPortItem") == 0)
     436                        pItem = new EthernetPortItem();
     437                    else
     438                        continue;
     439                    vsys.vecHardwareItems.push_back(pItem);
     440                    pItem->ulLineNumber = pelmItem->getLineNumber();
     441                    pItem->fillItem(pelmItem);
     442
     443                    /* validate */
     444                    try
     445                    {
     446                        pItem->checkConsistencyAndCompliance();
    425447                    }
    426448                    catch (OVFLogicError &e)
    427449                    {
    428                         throw OVFLogicError(N_("Error reading \"%s\": \"%s\""),
    429                                             m_strPath.c_str(),
    430                                             e.what());
     450                        throw OVFLogicError(N_("Error reading \"%s\": \"%s\""), m_strPath.c_str(), e.what());
    431451                    }
    432452
    433                     // store!
    434                     vsys.mapHardwareItems[i.ulInstanceID] = i;
    435                 }
    436             }
    437 
    438             {
    439                 xml::NodesLoop loopVirtualHardwareItems(*pelmThis, "StorageItem");// all "StorageItem" child elements
    440                 const xml::ElementNode *pelmItem;
    441                 while ((pelmItem = loopVirtualHardwareItems.forAllNodes()))
    442                 {
    443                     StorageItem i;
    444 
    445                     i.ulLineNumber = pelmItem->getLineNumber();
    446                     i.fillItem(pelmItem);
    447 
    448                     try
     453                    /* Add to mapping vector (for parent ID lookups) if it has a valid instance ID. */
     454                    if (pItem->ulInstanceID != 0)
    449455                    {
    450                         i.checkConsistencyAndCompliance();
     456                        std::map<uint32_t, const VirtualHardwareItem *>::const_iterator itDup;
     457                        itDup = mapHardwareItems.find(pItem->ulInstanceID);
     458                        if (itDup == mapHardwareItems.end())
     459                            mapHardwareItems[pItem->ulInstanceID] = pItem;
     460                        else
     461#if 1
     462                            LogRel(("OVFREADER: Warning reading '%s'! Duplicate ulInstanceID %u on line %u, previous at %u!\n",
     463                                    m_strPath.c_str(), pItem->ulInstanceID, pItem->ulLineNumber, itDup->second->ulLineNumber));
     464#else
     465                            throw OVFLogicError(N_("Error reading '%s': Duplicate ulInstanceID %u on line %u, previous at %u"),
     466                                                m_strPath.c_str(), pItem->ulInstanceID,
     467                                                pItem->ulLineNumber, itDup->second->ulLineNumber);
     468#endif
    451469                    }
    452                     catch (OVFLogicError &e)
    453                     {
    454                         throw OVFLogicError(N_("Error reading \"%s\": \"%s\""),
    455                                             m_strPath.c_str(),
    456                                             e.what());
    457                     }
    458 
    459                     vsys.mapHardwareItems[i.ulInstanceID] = i;
    460                 }
    461             }
    462 
    463             {
    464                 xml::NodesLoop loopVirtualHardwareItems(*pelmThis, "EthernetPortItem");// all "EthernetPortItem" child elements
    465                 const xml::ElementNode *pelmItem;
    466                 while ((pelmItem = loopVirtualHardwareItems.forAllNodes()))
    467                 {
    468                     EthernetPortItem i;
    469 
    470                     i.ulLineNumber = pelmItem->getLineNumber();
    471                     i.fillItem(pelmItem);
    472 
    473                     try{
    474                         i.checkConsistencyAndCompliance();
    475                     }
    476                     catch (OVFLogicError &e)
    477                     {
    478                         throw OVFLogicError(N_("Error reading \"%s\": \"%s\""),
    479                                             m_strPath.c_str(),
    480                                             e.what());
    481                     }
    482 
    483                     vsys.mapHardwareItems[i.ulInstanceID] = i;
    484470                }
    485471            }
     
    490476            // in this first loop we handle all items _except_ hard disk images,
    491477            // which we'll handle in a second loop below
    492             HardwareItemsMap::const_iterator itH;
    493             for (itH = vsys.mapHardwareItems.begin();
    494                  itH != vsys.mapHardwareItems.end();
    495                  ++itH)
     478            HardwareItemVector::const_iterator itH;
     479            for (itH = vsys.vecHardwareItems.begin(); itH != vsys.vecHardwareItems.end(); ++itH)
    496480            {
    497                 const VirtualHardwareItem &i = itH->second;
     481                const VirtualHardwareItem &i = **itH;
    498482
    499483                // do some analysis
     
    719703            // hard disk images; otherwise the code would fail if a hard
    720704            // disk image appears in the OVF before its hard disk controller
    721             for (itH = vsys.mapHardwareItems.begin();
    722                  itH != vsys.mapHardwareItems.end();
    723                  ++itH)
     705            for (itH = vsys.vecHardwareItems.begin(); itH != vsys.vecHardwareItems.end(); ++itH)
    724706            {
    725                 const VirtualHardwareItem &i = itH->second;
     707                const VirtualHardwareItem &i = **itH;
    726708
    727709                // do some analysis
     
    817799        }
    818800    }
    819 
    820     // now create the virtual system
    821     m_llVirtualSystems.push_back(vsys);
    822801}
    823802
     
    835814        else if (!strcmp(pcszItemChildName, "ElementName"))
    836815            strElementName = pelmItemChild->getValue();
    837         else if ((!strcmp(pcszItemChildName, "InstanceID"))
    838                  ||(!strcmp(pcszItemChildName, "InstanceId"))
    839                 )
     816        else if (   !strcmp(pcszItemChildName, "InstanceID")
     817                 || !strcmp(pcszItemChildName, "InstanceId") )
    840818            pelmItemChild->copyValue(ulInstanceID);
    841819        else if (!strcmp(pcszItemChildName, "HostResource"))
     
    902880{
    903881    RTCString name = getItemName();
     882    if (resourceType == 0)
     883        throw OVFLogicError(N_("Empty element ResourceType under %s element, line %d. see DMTF Schema Documentation %s"),
     884                            name.c_str(), ulLineNumber, DTMF_SPECS_URI);
     885
     886    /* Don't be too uptight about the ulInstanceID value.  There are OVAs out
     887       there which have ulInstanceID="%iid% for memory for instance, which is
     888       no good reason for not being able to process them.  bugref:8997 */
    904889    if (ulInstanceID == 0)
    905         throw OVFLogicError(N_("Element InstanceID is absent under %s element, line %d. "
    906                                "see DMTF Schema Documentation %s"),
    907                 name.c_str(), ulLineNumber, DTMF_SPECS_URI);
    908     if (resourceType == 0)
    909         throw OVFLogicError(N_("Empty element ResourceType under %s element, line %d. "
    910                                "see DMTF Schema Documentation %s"),
    911                 name.c_str(), ulLineNumber, DTMF_SPECS_URI);
     890    {
     891        if (   resourceType == ResourceType_IDEController
     892            || resourceType == ResourceType_OtherStorageDevice
     893            || resourceType == ResourceType_ParallelSCSIHBA
     894            || resourceType == ResourceType_iSCSIHBA //??
     895            || resourceType == ResourceType_IBHCA )  //??
     896            throw OVFLogicError(N_("Element InstanceID is absent under %s element, line %d. see DMTF Schema Documentation %s"),
     897                                name.c_str(), ulLineNumber, DTMF_SPECS_URI);
     898        else
     899            LogRel(("OVFREADER: Warning: Ignoring missing or invalid ulInstanceID under element %s, line %u\n",
     900                    name.c_str(), ulLineNumber));
     901    }
    912902}
    913903
Note: See TracChangeset for help on using the changeset viewer.

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