VirtualBox

Changeset 17417 in vbox for trunk


Ignore:
Timestamp:
Mar 5, 2009 4:39:39 PM (16 years ago)
Author:
vboxsync
Message:

OVF: more XML write and export.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/xml.h

    r17362 r17417  
    168168};
    169169
     170class VBOXXML_CLASS ENodeIsNotElement : public LogicError
     171{
     172public:
     173    ENodeIsNotElement(const char *aMsg = NULL) : LogicError(aMsg) {}
     174    ENodeIsNotElement(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     175};
     176
    170177// Runtime errors
    171178//////////////////////////////////////////////////////////////////////////////
     
    420427};
    421428
    422 /*
     429/**
    423430 * Node:
    424  *  an XML node, which represents either an element or an attribute.
     431 *  an XML node, which represents either an element or text content
     432 *  or an attribute.
    425433 *
    426434 *  For elements, getName() returns the element name, and getValue()
     
    435443 *  --  xml::Document::createRootElement()
    436444 *  --  xml::Node::createChild()
     445 *  --  xml::Node::addContent()
    437446 *  --  xml::Node::setAttribute()
    438447 */
     
    467476
    468477    Node* createChild(const char *pcszElementName);
     478    Node* addContent(const char *pcszContent);
    469479    Node* setAttribute(const char *pcszName, const char *pcszValue);
    470480
  • trunk/src/VBox/Main/ApplianceImpl.cpp

    r17400 r17417  
    3838using namespace std;
    3939
    40 // defines
     40////////////////////////////////////////////////////////////////////////////////
     41//
     42// hardware definitions
     43//
    4144////////////////////////////////////////////////////////////////////////////////
    4245
     
    112115struct VirtualSystem;
    113116
    114 // opaque private instance data of Appliance class
    115 struct Appliance::Data
    116 {
    117     Utf8Str                 strPath;            // file name last given to either read() or write()
    118 
    119     DiskImagesMap           mapDisks;           // map of DiskImage structs, sorted by DiskImage.strDiskId
    120 
    121     NetworksMap             mapNetworks;        // map of Network structs, sorted by Network.strNetworkName
    122 
    123     list<VirtualSystem>     llVirtualSystems;
    124 
    125     list< ComObjPtr<VirtualSystemDescription> > virtualSystemDescriptions;
    126 };
    127 
    128117typedef map<uint32_t, VirtualHardwareItem> HardwareItemsMap;
    129118
     
    198187    }
    199188};
     189
     190////////////////////////////////////////////////////////////////////////////////
     191//
     192// Appliance data definition
     193//
     194////////////////////////////////////////////////////////////////////////////////
     195
     196// opaque private instance data of Appliance class
     197struct Appliance::Data
     198{
     199    Utf8Str                 strPath;            // file name last given to either read() or write()
     200
     201    DiskImagesMap           mapDisks;           // map of DiskImage structs, sorted by DiskImage.strDiskId
     202
     203    NetworksMap             mapNetworks;        // map of Network structs, sorted by Network.strNetworkName
     204
     205    list<VirtualSystem>     llVirtualSystems;   // list of virtual systems, created by and valid after read()
     206
     207    list< ComObjPtr<VirtualSystemDescription> > virtualSystemDescriptions; //
     208};
     209
     210struct VirtualSystemDescription::Data
     211{
     212    list<VirtualSystemDescriptionEntry> llDescriptions;
     213    list<Utf8Str> llWarnings;
     214};
     215
     216////////////////////////////////////////////////////////////////////////////////
     217//
     218// Threads
     219//
     220////////////////////////////////////////////////////////////////////////////////
    200221
    201222struct Appliance::TaskImportMachines
     
    24552476    {
    24562477        xml::Document doc;
    2457         doc.createRootElement("Envelope");
    2458 
     2478        xml::Node *pelmRoot = doc.createRootElement("Envelope");
     2479
     2480        pelmRoot->setAttribute("ovf:version", "1.0");
     2481        pelmRoot->setAttribute("xml:lang", "en-US");
     2482        pelmRoot->setAttribute("xmlns", "http://schemas.dmtf.org/ovf/envelope/1");
     2483        pelmRoot->setAttribute("xmlns:ovf", "http://schemas.dmtf.org/ovf/envelope/1");
     2484        pelmRoot->setAttribute("xmlns:ovfstr", "http://schema.dmtf.org/ovf/strings/1");
     2485        pelmRoot->setAttribute("xmlns:rasd", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ResourceAllocationSettingData");
     2486        pelmRoot->setAttribute("xmlns:vssd", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_VirtualSystemSettingData");
     2487        pelmRoot->setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
     2488        pelmRoot->setAttribute("xsi:schemaLocation", "http://schemas.dmtf.org/ovf/envelope/1 ../ovf-envelope.xsd");
     2489
     2490
     2491        // <Envelope>/<References>
     2492        xml::Node *pelmReferences = pelmRoot->createChild("References");
     2493                // @ŧodo
     2494
     2495        /* <Envelope>/<DiskSection>:
     2496            <DiskSection>
     2497                <Info>List of the virtual disks used in the package</Info>
     2498                <Disk ovf:capacity="4294967296" ovf:diskId="lamp" ovf:format="http://www.vmware.com/specifications/vmdk.html#compressed" ovf:populatedSize="1924967692"/>
     2499            </DiskSection> */
     2500        xml::Node *pelmDiskSection = pelmRoot->createChild("DiskSection");
     2501        xml::Node *pelmDiskSectionInfo = pelmDiskSection->createChild("Info");
     2502        pelmDiskSectionInfo->addContent("List of the virtual disks used in the package");
     2503        // @todo for each disk:
     2504        // xml::Node *pelmDisk = pelmDiskSection->createChild("Disk");
     2505
     2506        /* <Envelope>/<NetworkSection>:
     2507            <NetworkSection>
     2508                <Info>Logical networks used in the package</Info>
     2509                <Network ovf:name="VM Network">
     2510                    <Description>The network that the LAMP Service will be available on</Description>
     2511                </Network>
     2512            </NetworkSection> */
     2513        xml::Node *pelmNetworkSection = pelmRoot->createChild("NetworkSection");
     2514        xml::Node *pelmNetworkSectionInfo = pelmNetworkSection->createChild("Info");
     2515        pelmNetworkSectionInfo->addContent("Logical networks used in the package");
     2516        // @todo for each network:
     2517        // xml::Node *pelmNetwork = pelmNetworkSection->createChild("Network");
     2518
     2519        // and here come the virtual systems:
     2520        xml::Node *pelmVirtualSystemCollection = pelmRoot->createChild("VirtualSystemCollection");
     2521        xml::Node *pattrVirtualSystemCollectionId = pelmVirtualSystemCollection->setAttribute("ovf:id", "ExportedVirtualBoxMachines");      // whatever
     2522
     2523        list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
     2524        /* Iterate through all virtual systems of that appliance */
     2525        for (it = pAppliance->m->virtualSystemDescriptions.begin();
     2526             it != pAppliance->m->virtualSystemDescriptions.end();
     2527             ++it)
     2528        {
     2529            ComObjPtr<VirtualSystemDescription> vsdescThis = (*it);
     2530
     2531            xml::Node *pelmVirtualSystem = pelmVirtualSystemCollection->createChild("VirtualSystem");
     2532            xml::Node *pelmVirtualSystemInfo = pelmVirtualSystem->createChild("Info");      // @todo put in description here after implementing an entry for it
     2533
     2534            std::list<VirtualSystemDescriptionEntry*> llName = vsdescThis->findByType(VirtualSystemDescriptionType_Name);
     2535
     2536            std::list<VirtualSystemDescriptionEntry*> llOS = vsdescThis->findByType(VirtualSystemDescriptionType_OS);
     2537            /*  <OperatingSystemSection ovf:id="82">
     2538                    <Info>Guest Operating System</Info>
     2539                    <Description>Linux 2.6.x</Description>
     2540                </OperatingSystemSection> */
     2541            xml::Node *pelmOperatingSystemSection = pelmVirtualSystem->createChild("OperatingSystemSection");
     2542            pelmOperatingSystemSection->setAttribute("ovf:id", "82");
     2543                    // @todo convert vbox OS type into OVF ID
     2544            pelmOperatingSystemSection->createChild("Info")->addContent("blah");        // @ŧodo
     2545            pelmOperatingSystemSection->createChild("Description")->addContent("blah");        // @ŧodo
     2546
     2547            // <VirtualHardwareSection ovf:id="hw1" ovf:transport="iso">
     2548            xml::Node *pelmVirtualHardwareSection = pelmVirtualSystem->createChild("VirtualHardwareSection");
     2549
     2550            /*  <System>
     2551                    <vssd:Description>Description of the virtual hardware section.</vssd:Description>
     2552                    <vssd:ElementName>vmware</vssd:ElementName>
     2553                    <vssd:InstanceID>1</vssd:InstanceID>
     2554                    <vssd:VirtualSystemIdentifier>MyLampService</vssd:VirtualSystemIdentifier>
     2555                    <vssd:VirtualSystemType>vmx-4</vssd:VirtualSystemType>
     2556                </System> */
     2557            xml::Node *pelmSystem = pelmVirtualHardwareSection->createChild("System");
     2558
     2559            // <vssd:VirtualSystemType>vmx-4</vssd:VirtualSystemType>
     2560            xml::Node *pelmVirtualSystemType = pelmSystem->createChild("VirtualSystemType");
     2561            pelmVirtualSystemType->addContent("virtualbox-2.2");            // instead of vmx-7?
     2562
     2563            uint32_t ulInstanceID = 1;
     2564
     2565            list<VirtualSystemDescriptionEntry>::const_iterator itD;
     2566            for (itD = vsdescThis->m->llDescriptions.begin();
     2567                 itD != vsdescThis->m->llDescriptions.end();
     2568                 ++itD)
     2569            {
     2570                const VirtualSystemDescriptionEntry &desc = *itD;
     2571
     2572                OVFResourceType_T type = 0;     // if this becomes != 0 then we do stuff
     2573                Utf8Str strDescription;         // must also be set then
     2574                int32_t lVirtualQuantity = -1;
     2575                uint64_t uTemp;
     2576
     2577                switch (desc.type)
     2578                {
     2579                    case VirtualSystemDescriptionType_CPU:
     2580                        /*  <Item>
     2581                                <rasd:Caption>1 virtual CPU</rasd:Caption>
     2582                                <rasd:Description>Number of virtual CPUs</rasd:Description>
     2583                                <rasd:ElementName>virtual CPU</rasd:ElementName>
     2584                                <rasd:InstanceID>1</rasd:InstanceID>
     2585                                <rasd:ResourceType>3</rasd:ResourceType>
     2586                                <rasd:VirtualQuantity>1</rasd:VirtualQuantity>
     2587                            </Item> */
     2588                        strDescription = "Number of virtual CPUs";
     2589                        type = OVFResourceType_Processor; // 3
     2590                        lVirtualQuantity = 1;
     2591                    break;
     2592
     2593                    case VirtualSystemDescriptionType_Memory:
     2594                        /*  <Item>
     2595                                <rasd:AllocationUnits>MegaBytes</rasd:AllocationUnits>
     2596                                <rasd:Caption>256 MB of memory</rasd:Caption>
     2597                                <rasd:Description>Memory Size</rasd:Description>
     2598                                <rasd:ElementName>Memory</rasd:ElementName>
     2599                                <rasd:InstanceID>2</rasd:InstanceID>
     2600                                <rasd:ResourceType>4</rasd:ResourceType>
     2601                                <rasd:VirtualQuantity>256</rasd:VirtualQuantity>
     2602                            </Item> */
     2603                        strDescription = "Memory Size";
     2604                        type = OVFResourceType_Memory; // 4
     2605                        desc.strVbox.toInt(uTemp);
     2606                        lVirtualQuantity = uTemp / _1M;
     2607                    break;
     2608
     2609                    case VirtualSystemDescriptionType_HardDiskControllerIDE:
     2610                    break;
     2611                    case VirtualSystemDescriptionType_HardDiskControllerSATA:
     2612                    break;
     2613                    case VirtualSystemDescriptionType_HardDiskControllerSCSI:
     2614                    break;
     2615
     2616                    case VirtualSystemDescriptionType_HardDiskImage:
     2617                    break;
     2618
     2619                    case VirtualSystemDescriptionType_Floppy:
     2620                    break;
     2621
     2622                    case VirtualSystemDescriptionType_CDROM:
     2623                    break;
     2624
     2625                    case VirtualSystemDescriptionType_LogicalNetwork:
     2626                    break;
     2627
     2628                    case VirtualSystemDescriptionType_NetworkAdapter:
     2629                    break;
     2630
     2631                    case VirtualSystemDescriptionType_USBController:
     2632                    break;
     2633
     2634                    case VirtualSystemDescriptionType_SoundCard:
     2635                    break;
     2636                }
     2637
     2638                if (type)
     2639                {
     2640                    xml::Node *pItem;
     2641                    pItem = pelmVirtualHardwareSection->createChild("Item");
     2642
     2643                    pItem->createChild("rasd:Description")->addContent(strDescription.c_str());
     2644
     2645                    // <rasd:InstanceID>1</rasd:InstanceID>
     2646                    pItem->createChild("rasd:InstanceID")->addContent(Utf8StrFmt("%d", ulInstanceID).c_str());
     2647
     2648                    // <rasd:ResourceType>3</rasd:ResourceType>
     2649                    pItem->createChild("rasd:ResourceType")->addContent(Utf8StrFmt("%d", type).c_str());
     2650
     2651                    // <rasd:VirtualQuantity>1</rasd:VirtualQuantity>
     2652                    if (lVirtualQuantity != -1)
     2653                        pItem->createChild("rasd:VirtualQuantity")->addContent(Utf8StrFmt("%d", lVirtualQuantity).c_str());
     2654
     2655                }
     2656            }
     2657        }
     2658
     2659        // now go write the XML
    24592660        xml::XmlFileWriter writer(doc);
    24602661        writer.write(pAppliance->m->strPath.c_str());
     
    24812682}
    24822683
    2483 #
    24842684////////////////////////////////////////////////////////////////////////////////
    24852685//
     
    24902690DEFINE_EMPTY_CTOR_DTOR(VirtualSystemDescription)
    24912691struct shutup3 {};
    2492 
    2493 struct VirtualSystemDescription::Data
    2494 {
    2495     list<VirtualSystemDescriptionEntry> descriptions;
    2496     list<Utf8Str> warnings;
    2497 };
    24982692
    24992693/**
     
    25462740    AutoReadLock alock(this);
    25472741
    2548     *aCount = (ULONG)m->descriptions.size();
     2742    *aCount = (ULONG)m->llDescriptions.size();
    25492743
    25502744    return S_OK;
     
    25732767    AutoReadLock alock(this);
    25742768
    2575     ULONG c = (ULONG)m->descriptions.size();
     2769    ULONG c = (ULONG)m->llDescriptions.size();
    25762770    com::SafeArray<VirtualSystemDescriptionType_T> sfaTypes(c);
    25772771    com::SafeArray<BSTR> sfaRefs(c);
     
    25822776    list<VirtualSystemDescriptionEntry>::const_iterator it;
    25832777    size_t i = 0;
    2584     for (it = m->descriptions.begin();
    2585          it != m->descriptions.end();
     2778    for (it = m->llDescriptions.begin();
     2779         it != m->llDescriptions.end();
    25862780         ++it, ++i)
    25872781    {
     
    26312825    com::SafeArray<IN_BSTR> aExtraConfigValues(ComSafeArrayInArg(argExtraConfigValues));
    26322826
    2633     if (    (aVboxValues.size() != m->descriptions.size())
    2634          || (aExtraConfigValues.size() != m->descriptions.size())
     2827    if (    (aVboxValues.size() != m->llDescriptions.size())
     2828         || (aExtraConfigValues.size() != m->llDescriptions.size())
    26352829       )
    26362830        return E_INVALIDARG;
     
    26382832    list<VirtualSystemDescriptionEntry>::iterator it;
    26392833    size_t i = 0;
    2640     for (it = m->descriptions.begin();
    2641          it != m->descriptions.end();
     2834    for (it = m->llDescriptions.begin();
     2835         it != m->llDescriptions.end();
    26422836         ++it, ++i)
    26432837    {
     
    26702864    AutoReadLock alock(this);
    26712865
    2672     com::SafeArray<BSTR> sfaWarnings(m->warnings.size());
     2866    com::SafeArray<BSTR> sfaWarnings(m->llWarnings.size());
    26732867
    26742868    list<Utf8Str>::const_iterator it;
    26752869    size_t i = 0;
    2676     for (it = m->warnings.begin();
    2677          it != m->warnings.end();
     2870    for (it = m->llWarnings.begin();
     2871         it != m->llWarnings.end();
    26782872         ++it, ++i)
    26792873    {
     
    27022896{
    27032897    VirtualSystemDescriptionEntry vsde;
    2704     vsde.ulIndex = (uint32_t)m->descriptions.size();      // each entry gets an index so the client side can reference them
     2898    vsde.ulIndex = (uint32_t)m->llDescriptions.size();      // each entry gets an index so the client side can reference them
    27052899    vsde.type = aType;
    27062900    vsde.strRef = strRef;
     
    27092903    vsde.strExtraConfig = strExtraConfig;
    27102904
    2711     m->descriptions.push_back(vsde);
     2905    m->llDescriptions.push_back(vsde);
    27122906}
    27132907
     
    27182912    Utf8StrFmtVA str(aWarning, args);
    27192913    va_end(args);
    2720     m->warnings.push_back(str);
     2914    m->llWarnings.push_back(str);
    27212915}
    27222916
     
    27322926
    27332927    list<VirtualSystemDescriptionEntry>::iterator it;
    2734     for (it = m->descriptions.begin();
    2735          it != m->descriptions.end();
     2928    for (it = m->llDescriptions.begin();
     2929         it != m->llDescriptions.end();
    27362930         ++it)
    27372931    {
     
    27542948    Utf8Str strRef = Utf8StrFmt("%RI32", id);
    27552949    list<VirtualSystemDescriptionEntry>::const_iterator it;
    2756     for (it = m->descriptions.begin();
    2757          it != m->descriptions.end();
     2950    for (it = m->llDescriptions.begin();
     2951         it != m->llDescriptions.end();
    27582952         ++it)
    27592953    {
     
    28773071        /* Memory */
    28783072        Utf8Str strMemory = Utf8StrFmt("%RI32", (uint64_t)ulMemSizeMB * _1M);
    2879         pNewDesc->addEntry(VirtualSystemDescriptionType_CPU,
     3073        pNewDesc->addEntry(VirtualSystemDescriptionType_Memory,
    28803074                           "",
    28813075                           strMemory,
  • trunk/src/VBox/Main/xml/xml.cpp

    r17400 r17417  
    411411struct Node::Data
    412412{
    413     xmlNode     *plibNode;          // != NULL if this is an element
    414     xmlAttr     *plibAttr;          // != NULL if this is an attribute
     413    xmlNode     *plibNode;          // != NULL if this is an element or content node
     414    xmlAttr     *plibAttr;          // != NULL if this is an attribute node
    415415
    416416    Node        *pParent;           // NULL only for the root element
    417     const char  *pcszName;          // points either into plibNode or plibAttr
     417    const char  *pcszName;          // element or attribute name, points either into plibNode or plibAttr;
     418                                    // NULL if this is a content node
    418419
    419420    struct compare_const_char
     
    748749    return false;
    749750}
     751
     752/**
     753 * Creates a new child element node and appends it to the list
     754 * of children in "this".
     755 *
     756 * @param pcszElementName
     757 * @return
     758 */
     759Node* Node::createChild(const char *pcszElementName)
     760{
     761    // we must be an element, not an attribute
     762    if (!m->plibNode)
     763        throw ENodeIsNotElement(RT_SRC_POS);
     764
     765    // libxml side: create new node
     766    xmlNode *plibNode;
     767    if (!(plibNode = xmlNewNode(NULL,        // namespace
     768                                (const xmlChar*)pcszElementName)))
     769        throw ENoMemory();
     770    xmlAddChild(m->plibNode, plibNode);
     771
     772    // now wrap this in C++
     773    Node *p = new Node;
     774    boost::shared_ptr<Node> pNew(p);
     775    pNew->m->plibNode = plibNode;
     776    pNew->m->pcszName = (const char*)plibNode->name;
     777
     778    m->children.push_back(pNew);
     779
     780    return p;
     781}
     782
     783
     784/**
     785 * Creates a content node and appends it to the list of children
     786 * in "this".
     787 *
     788 * @param pcszElementName
     789 * @return
     790 */
     791Node* Node::addContent(const char *pcszContent)
     792{
     793    // we must be an element, not an attribute
     794    if (!m->plibNode)
     795        throw ENodeIsNotElement(RT_SRC_POS);
     796
     797    // libxml side: create new node
     798    xmlNode *plibNode;
     799    if (!(plibNode = xmlNewText((const xmlChar*)pcszContent)))
     800        throw ENoMemory();
     801    xmlAddChild(m->plibNode, plibNode);
     802
     803    // now wrap this in C++
     804    Node *p = new Node;
     805    boost::shared_ptr<Node> pNew(p);
     806    pNew->m->plibNode = plibNode;
     807    pNew->m->pcszName = NULL;
     808
     809    m->children.push_back(pNew);
     810
     811}
     812
     813/**
     814 * Sets the given attribute. Assumes that "this" is an element node,
     815 * otherwise ENodeIsNotElement is thrown.
     816 *
     817 * If an attribute with the given name exists, it is overwritten,
     818 * otherwise a new attribute is created. Returns the attribute node
     819 * that was either created or changed.
     820 *
     821 * @param pcszName
     822 * @param pcszValue
     823 * @return
     824 */
     825Node* Node::setAttribute(const char *pcszName, const char *pcszValue)
     826{
     827    // we must be an element, not an attribute
     828    if (!m->plibNode)
     829        throw ENodeIsNotElement(RT_SRC_POS);
     830
     831    Data::AttributesMap::const_iterator it;
     832
     833    it = m->attribs.find(pcszName);
     834    if (it == m->attribs.end())
     835    {
     836        // libxml side: xmlNewProp creates an attribute
     837        xmlAttr *plibAttr = xmlNewProp(m->plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
     838        const char *pcszAttribName = (const char*)plibAttr->name;
     839
     840        // C++ side: create an attribute node around it
     841        boost::shared_ptr<Node> pNew(new Node);
     842        pNew->m->plibAttr = plibAttr;
     843        pNew->m->pcszName = (const char*)plibAttr->name;
     844        pNew->m->pParent = this;
     845        // store
     846        m->attribs[pcszAttribName] = pNew;
     847    }
     848    else
     849    {
     850        // @todo
     851        throw LogicError("Attribute exists");
     852    }
     853
     854    return NULL;
     855
     856}
     857
    750858
    751859/*
     
    8991007Node* Document::createRootElement(const char *pcszRootElementName)
    9001008{
    901     if (m->pRootElement)
     1009    if (m->pRootElement || m->plibDocument)
    9021010        throw EDocumentNotEmpty(RT_SRC_POS);
    9031011
     1012    // libxml side: create document, create root node
    9041013    m->plibDocument = xmlNewDoc((const xmlChar*)"1.0");
    905     if (!(m->pRootElement = new Node()))
     1014    xmlNode *plibRootNode;
     1015    if (!(plibRootNode = xmlNewNode(NULL,        // namespace
     1016                                    (const xmlChar*)pcszRootElementName)))
    9061017        throw ENoMemory();
    907     Node::Data *pNodeData = m->pRootElement->m;
    908     if (!(pNodeData->plibNode = xmlNewNode(NULL,        // namespace
    909                                            (const xmlChar*)pcszRootElementName)))
    910         throw ENoMemory();
    911     pNodeData->pcszName = (const char*)pNodeData->plibNode->name;
     1018    xmlDocSetRootElement(m->plibDocument, plibRootNode);
     1019
     1020    // now wrap this in C++
     1021    m->pRootElement = new Node();
     1022    m->pRootElement->m->plibNode = plibRootNode;
     1023    m->pRootElement->m->pcszName = (const char*)plibRootNode->name;
    9121024
    9131025    return m->pRootElement;
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