VirtualBox

Changeset 29873 in vbox for trunk


Ignore:
Timestamp:
May 28, 2010 5:14:53 PM (15 years ago)
Author:
vboxsync
Message:

OVF: fix incorrect disk UUIDs in machine XML on export

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/com/Guid.h

    r28800 r29873  
    141141    }
    142142
     143    /**
     144     * Like toString, but encloses the returned string in curly brackets.
     145     * @return
     146     */
     147    Utf8Str toStringCurly() const
     148    {
     149        char buf[RTUUID_STR_LENGTH + 2] = "{";
     150        ::RTUuidToStr(&uuid, buf + 1, RTUUID_STR_LENGTH);
     151        buf[sizeof(buf) - 2] = '}';
     152        buf[sizeof(buf) - 1] = '\0';
     153        return Utf8Str(buf);
     154    }
     155
    143156    Bstr toUtf16() const
    144157    {
  • trunk/include/VBox/settings.h

    r29480 r29873  
    9393
    9494    com::Utf8Str makeString(const RTTIMESPEC &tm);
    95     com::Utf8Str makeString(const com::Guid &guid);
    9695
    9796    void readExtraData(const xml::ElementNode &elmExtraData,
     
    880879        BuildMachineXML_SkipRemovableMedia = 0x02
    881880    };
    882     void buildMachineXML(xml::ElementNode &elmMachine, uint32_t fl);
     881    void buildMachineXML(xml::ElementNode &elmMachine,
     882                         uint32_t fl,
     883                         std::list<xml::ElementNode*> *pllElementsWithUuidAttributes);
    883884
    884885private:
     
    901902    void buildHardwareXML(xml::ElementNode &elmParent, const Hardware &hw, const Storage &strg);
    902903    void buildNetworkXML(NetworkAttachmentType_T mode, xml::ElementNode &elmParent, const NetworkAdapter &nic);
    903     void buildStorageControllersXML(xml::ElementNode &elmParent, const Storage &st, bool fSkipRemovableMedia);
     904    void buildStorageControllersXML(xml::ElementNode &elmParent,
     905                                    const Storage &st,
     906                                    bool fSkipRemovableMedia,
     907                                    std::list<xml::ElementNode*> *pllElementsWithUuidAttributes);
    904908    void buildSnapshotXML(xml::ElementNode &elmParent, const Snapshot &snap);
    905909
  • trunk/src/VBox/Main/ApplianceImplExport.cpp

    r29389 r29873  
    661661 */
    662662void Appliance::buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSystemsTo,
     663                                            std::list<xml::ElementNode*> *pllElementsWithUuidAttributes,
    663664                                            ComObjPtr<VirtualSystemDescription> &vsdescThis,
    664665                                            OVFFormat enFormat,
     
    12981299        pConfig->buildMachineXML(*pelmVBoxMachine,
    12991300                                   settings::MachineConfigFile::BuildMachineXML_WriteVboxVersionAttribute
    1300                                  | settings::MachineConfigFile::BuildMachineXML_SkipRemovableMedia);
     1301                                 | settings::MachineConfigFile::BuildMachineXML_SkipRemovableMedia,
    13011302                                        // but not BuildMachineXML_IncludeSnapshots
     1303                                 pllElementsWithUuidAttributes);
    13021304        delete pConfig;
    13031305    }
     
    14251427            pelmToAddVirtualSystemsTo = pelmRoot;       // add virtual system directly under root element
    14261428
     1429        // this list receives pointers to the XML elements in the machine XML which
     1430        // might have UUIDs that need fixing after we know the UUIDs of the exported images
     1431        std::list<xml::ElementNode*> llElementsWithUuidAttributes;
     1432
    14271433        list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
    14281434        /* Iterate throughs all virtual systems of that appliance */
     
    14331439            ComObjPtr<VirtualSystemDescription> vsdescThis = *it;
    14341440            buildXMLForOneVirtualSystem(*pelmToAddVirtualSystemsTo,
     1441                                        &llElementsWithUuidAttributes,
    14351442                                        vsdescThis,
    14361443                                        enFormat,
     
    15371544            // capacity is reported in megabytes, so...
    15381545            cbCapacity *= _1M;
     1546
     1547            Bstr uuidTarget;
     1548            rc = pTargetDisk->COMGETTER(Id)(uuidTarget.asOutParam());
     1549            if (FAILED(rc)) throw rc;
     1550            Guid guidTarget(uuidTarget);
    15391551
    15401552            // upon success, close the disk as well
     
    15621574                                                                                    // correct string as communicated to us by VMware (public bug #6612)
    15631575                                  );
    1564             pelmDisk->setAttribute("vbox:uuid", Utf8StrFmt("%RTuuid", guidSource.raw()).c_str());
     1576
     1577            // add the UUID of the newly created target image to the OVF disk element, but in the
     1578            // vbox: namespace since it's not part of the standard
     1579            pelmDisk->setAttribute("vbox:uuid", Utf8StrFmt("%RTuuid", guidTarget.raw()).c_str());
     1580
     1581            // now, we might have other XML elements from vbox:Machine pointing to this image,
     1582            // but those would refer to the UUID of the _source_ image (which we created the
     1583            // export image from); those UUIDs need to be fixed to the export image
     1584            for (std::list<xml::ElementNode*>::iterator eit = llElementsWithUuidAttributes.begin();
     1585                 eit != llElementsWithUuidAttributes.end();
     1586                 ++eit)
     1587            {
     1588                xml::ElementNode *pelmImage = *eit;
     1589                // overwrite existing uuid attribute
     1590                pelmImage->setAttribute("uuid", guidTarget.toStringCurly());
     1591            }
    15651592        }
    15661593
  • trunk/src/VBox/Main/ApplianceImplImport.cpp

    r29777 r29873  
    5050
    5151/**
    52  * Public method implementation.
     52 * Public method implementation. This opens the OVF with ovfreader.cpp.
     53 * Thread implementation is in Appliance::readImpl().
     54 *
    5355 * @param path
    5456 * @return
     
    100102
    101103/**
    102  * Public method implementation.
     104 * Public method implementation. This looks at the output of ovfreader.cpp and creates
     105 * VirtualSystemDescription instances.
    103106 * @return
    104107 */
     
    539542
    540543/**
    541  * Public method implementation.
     544 * Public method implementation. This creates one or more new machines according to the
     545 * VirtualSystemScription instances created by Appliance::Interpret().
     546 * Thread implementation is in Appliance::importImpl().
    542547 * @param aProgress
    543548 * @return
     
    587592 * Implementation for reading an OVF. This starts a new thread which will call
    588593 * Appliance::taskThreadImportOrExport() which will then call readFS() or readS3().
     594 * This will then open the OVF with ovfreader.cpp.
    589595 *
    590596 * This is in a separate private method because it is used from two locations:
     
    635641/**
    636642 * Actual worker code for reading an OVF from disk. This is called from Appliance::taskThreadImportOrExport()
    637  * and therefore runs on the OVF read worker thread. This runs in two contexts:
     643 * and therefore runs on the OVF read worker thread. This opens the OVF with ovfreader.cpp.
     644 *
     645 * This runs in two contexts:
    638646 *
    639647 * 1) in a first worker thread; in that case, Appliance::Read() called Appliance::readImpl();
     
    912920 * Appliance::taskThreadImportOrExport().
    913921 *
     922 * This creates one or more new machines according to the VirtualSystemScription instances created by
     923 * Appliance::Interpret().
     924 *
    914925 * This is in a separate private method because it is used from two locations:
    915926 *
     
    10721083/**
    10731084 * Actual worker code for importing OVF data into VirtualBox. This is called from Appliance::taskThreadImportOrExport()
    1074  * and therefore runs on the OVF import worker thread. This runs in two contexts:
     1085 * and therefore runs on the OVF import worker thread. This creates one or more new machines according to the
     1086 * VirtualSystemScription instances created by Appliance::Interpret().
     1087 *
     1088 * This runs in two contexts:
    10751089 *
    10761090 * 1) in a first worker thread; in that case, Appliance::ImportMachines() called Appliance::importImpl();
     
    13131327            // First open the existing disk image
    13141328            rc = mVirtualBox->OpenHardDisk(Bstr(strSrcFilePath),
    1315                                         AccessMode_ReadOnly,
    1316                                         false,
    1317                                         NULL,
    1318                                         false,
    1319                                         NULL,
    1320                                         pSourceHD.asOutParam());
     1329                                           AccessMode_ReadOnly,
     1330                                           false,
     1331                                           NULL,
     1332                                           false,
     1333                                           NULL,
     1334                                           pSourceHD.asOutParam());
    13211335            if (FAILED(rc)) throw rc;
    13221336            fSourceHdNeedsClosing = true;
     
    13671381 * about what needs cleaning up (to support rollback).
    13681382 *
    1369  * @param locInfo
    1370  * @param vsysThis
    1371  * @param vsdescThis
    1372  * @param pNewMachine
    1373  * @param stack
     1383 * @param vsysThis OVF virtual system (machine) to import.
     1384 * @param vsdescThis  Matching virtual system description (machine) to import.
     1385 * @param pNewMachine out: Newly created machine.
     1386 * @param stack Cleanup stack for when this throws.
    13741387 */
    13751388void Appliance::importMachineGeneric(const ovf::VirtualSystem &vsysThis,
  • trunk/src/VBox/Main/include/ApplianceImpl.h

    r29422 r29873  
    168168    struct XMLStack;
    169169    void buildXMLForOneVirtualSystem(xml::ElementNode &elmToAddVirtualSystemsTo,
     170                                     std::list<xml::ElementNode*> *pllElementsWithUuidAttributes,
    170171                                     ComObjPtr<VirtualSystemDescription> &vsdescThis,
    171172                                     OVFFormat enFormat,
  • trunk/src/VBox/Main/xml/Settings.cpp

    r29593 r29873  
    427427                      (uint16_t)time.u8Minute,
    428428                      (uint16_t)time.u8Second);
    429 }
    430 
    431 /**
    432  * Helper to create a string for a GUID.
    433  * @param guid
    434  * @return
    435  */
    436 com::Utf8Str ConfigFileBase::makeString(const Guid &guid)
    437 {
    438     Utf8Str str("{");
    439     str.append(guid.toString());
    440     str.append("}");
    441     return str;
    442429}
    443430
     
    11621149{
    11631150    xml::ElementNode *pelmHardDisk = elmMedium.createChild("HardDisk");
    1164     pelmHardDisk->setAttribute("uuid", makeString(mdm.uuid));
     1151    pelmHardDisk->setAttribute("uuid", mdm.uuid.toStringCurly());
    11651152    pelmHardDisk->setAttribute("location", mdm.strLocation);
    11661153    pelmHardDisk->setAttribute("format", mdm.strFormat);
     
    12221209        const MachineRegistryEntry &mre = *it;
    12231210        xml::ElementNode *pelmMachineEntry = pelmMachineRegistry->createChild("MachineEntry");
    1224         pelmMachineEntry->setAttribute("uuid", makeString(mre.uuid));
     1211        pelmMachineEntry->setAttribute("uuid", mre.uuid.toStringCurly());
    12251212        pelmMachineEntry->setAttribute("src", mre.strSettingsFile);
    12261213    }
     
    12431230        const Medium &mdm = *it;
    12441231        xml::ElementNode *pelmMedium = pelmDVDImages->createChild("Image");
    1245         pelmMedium->setAttribute("uuid", makeString(mdm.uuid));
     1232        pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
    12461233        pelmMedium->setAttribute("location", mdm.strLocation);
    12471234        if (mdm.strDescription.length())
     
    12561243        const Medium &mdm = *it;
    12571244        xml::ElementNode *pelmMedium = pelmFloppyImages->createChild("Image");
    1258         pelmMedium->setAttribute("uuid", makeString(mdm.uuid));
     1245        pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
    12591246        pelmMedium->setAttribute("location", mdm.strLocation);
    12601247        if (mdm.strDescription.length())
     
    30633050         && (!hw.uuid.isEmpty())
    30643051       )
    3065         pelmHardware->setAttribute("uuid", makeString(hw.uuid));
     3052        pelmHardware->setAttribute("uuid", hw.uuid.toStringCurly());
    30663053
    30673054    xml::ElementNode *pelmCPU      = pelmHardware->createChild("CPU");
     
    32973284                        pelmDVD->setAttribute("passthrough", att.fPassThrough);
    32983285                        if (!att.uuid.isEmpty())
    3299                             pelmDVD->createChild("Image")->setAttribute("uuid", makeString(att.uuid));
     3286                            pelmDVD->createChild("Image")->setAttribute("uuid", att.uuid.toStringCurly());
    33003287                        else if (att.strHostDriveSrc.length())
    33013288                            pelmDVD->createChild("HostDrive")->setAttribute("src", att.strHostDriveSrc);
     
    33133300                    pelmFloppy->setAttribute("enabled", true);
    33143301                    if (!att.uuid.isEmpty())
    3315                         pelmFloppy->createChild("Image")->setAttribute("uuid", makeString(att.uuid));
     3302                        pelmFloppy->createChild("Image")->setAttribute("uuid", att.uuid.toStringCurly());
    33163303                    else if (att.strHostDriveSrc.length())
    33173304                        pelmFloppy->createChild("HostDrive")->setAttribute("src", att.strHostDriveSrc);
     
    36533640 *   This parameter is ignored unless the settings version is at least v1.9, which
    36543641 *   is always the case when this gets called for OVF export.
     3642 * @param pllElementsWithUuidAttributes If not NULL, must point to a list of element node
     3643 *   pointers to which we will append all allements that we created here that contain
     3644 *   UUID attributes. This allows the OVF export code to quickly replace the internal
     3645 *   media UUIDs with the UUIDs of the media that were exported.
    36553646 */
    36563647void MachineConfigFile::buildStorageControllersXML(xml::ElementNode &elmParent,
    36573648                                                   const Storage &st,
    3658                                                    bool fSkipRemovableMedia)
     3649                                                   bool fSkipRemovableMedia,
     3650                                                   std::list<xml::ElementNode*> *pllElementsWithUuidAttributes)
    36593651{
    36603652    xml::ElementNode *pelmStorageControllers = elmParent.createChild("StorageControllers");
     
    37593751            pelmDevice->setAttribute("device", att.lDevice);
    37603752
     3753            // attached image, if any
    37613754            if (    !att.uuid.isEmpty()
    37623755                 && (    att.deviceType == DeviceType_HardDisk
     
    37643757                    )
    37653758               )
    3766                 pelmDevice->createChild("Image")->setAttribute("uuid", makeString(att.uuid));
     3759            {
     3760                xml::ElementNode *pelmImage = pelmDevice->createChild("Image");
     3761                pelmImage->setAttribute("uuid", att.uuid.toStringCurly());
     3762
     3763                // if caller wants a list of UUID elements, give it to them
     3764                if (pllElementsWithUuidAttributes)
     3765                    pllElementsWithUuidAttributes->push_back(pelmImage);
     3766            }
    37673767            else if (    (m->sv >= SettingsVersion_v1_9)
    37683768                      && (att.strHostDriveSrc.length())
     
    37853785    xml::ElementNode *pelmSnapshot = elmParent.createChild("Snapshot");
    37863786
    3787     pelmSnapshot->setAttribute("uuid", makeString(snap.uuid));
     3787    pelmSnapshot->setAttribute("uuid", snap.uuid.toStringCurly());
    37883788    pelmSnapshot->setAttribute("name", snap.strName);
    37893789    pelmSnapshot->setAttribute("timeStamp", makeString(snap.timestamp));
     
    37983798    buildStorageControllersXML(*pelmSnapshot,
    37993799                               snap.storage,
    3800                                false /* fSkipRemovableMedia */);
     3800                               false /* fSkipRemovableMedia */,
     3801                               NULL); /* pllElementsWithUuidAttributes */
    38013802                                    // we only skip removable media for OVF, but we never get here for OVF
    38023803                                    // since snapshots never get written then
     
    38463847 * @param elmMachine XML <Machine> element to add attributes and elements to.
    38473848 * @param fl Flags.
     3849 * @param pllElementsWithUuidAttributes pointer to list that should receive UUID elements or NULL;
     3850 *        see buildStorageControllersXML() for details.
    38483851 */
    38493852void MachineConfigFile::buildMachineXML(xml::ElementNode &elmMachine,
    3850                                         uint32_t fl)
     3853                                        uint32_t fl,
     3854                                        std::list<xml::ElementNode*> *pllElementsWithUuidAttributes)
    38513855{
    38523856    if (fl & BuildMachineXML_WriteVboxVersionAttribute)
     
    38543858        setVersionAttribute(elmMachine);
    38553859
    3856     elmMachine.setAttribute("uuid", makeString(uuid));
     3860    elmMachine.setAttribute("uuid", uuid.toStringCurly());
    38573861    elmMachine.setAttribute("name", strName);
    38583862    if (!fNameSync)
     
    38653869    if (    (fl & BuildMachineXML_IncludeSnapshots)
    38663870         && !uuidCurrentSnapshot.isEmpty())
    3867         elmMachine.setAttribute("currentSnapshot", makeString(uuidCurrentSnapshot));
     3871        elmMachine.setAttribute("currentSnapshot", uuidCurrentSnapshot.toStringCurly());
    38683872    if (strSnapshotFolder.length())
    38693873        elmMachine.setAttribute("snapshotFolder", strSnapshotFolder);
     
    38973901    buildStorageControllersXML(elmMachine,
    38983902                               storageMachine,
    3899                                !!(fl & BuildMachineXML_SkipRemovableMedia));
     3903                               !!(fl & BuildMachineXML_SkipRemovableMedia),
     3904                               pllElementsWithUuidAttributes);
    39003905}
    39013906
     
    40854090        xml::ElementNode *pelmMachine = m->pelmRoot->createChild("Machine");
    40864091        buildMachineXML(*pelmMachine,
    4087                         MachineConfigFile::BuildMachineXML_IncludeSnapshots);
     4092                        MachineConfigFile::BuildMachineXML_IncludeSnapshots,
    40884093                            // but not BuildMachineXML_WriteVboxVersionAttribute
     4094                        NULL); /* pllElementsWithUuidAttributes */
    40894095
    40904096        // now go write the XML
  • trunk/src/VBox/Runtime/r3/xml.cpp

    r28800 r29873  
    10111011AttributeNode* ElementNode::setAttribute(const char *pcszName, const char *pcszValue)
    10121012{
     1013    AttributeNode *pattrReturn;
    10131014    Data::AttributesMap::const_iterator it;
    10141015
     
    10241025        // store
    10251026        m->attribs[pcszKey] = pNew;
     1027        pattrReturn = pNew.get();
    10261028    }
    10271029    else
    10281030    {
    1029         // @todo
    1030         throw LogicError("Attribute exists");
    1031     }
    1032 
    1033     return NULL;
     1031        // overwrite existing libxml attribute node
     1032        xmlAttrPtr plibAttr = xmlSetProp(m_plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
     1033
     1034        // and fix our existing C++ side around it
     1035        boost::shared_ptr<AttributeNode> pattr = it->second;
     1036        pattr->m_plibAttr = plibAttr;       // in case the xmlAttrPtr is different, I'm not sure
     1037
     1038        pattrReturn = pattr.get();
     1039    }
     1040
     1041    return pattrReturn;
    10341042
    10351043}
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