9
9
* The code can read all VirtualBox settings files version 1.3 and higher. That version was
10
10
* written by VirtualBox 2.0. It can write settings version 1.7 (used by VirtualBox 2.2 and
11
* 3.0) and 1.9 (used by VirtualBox 3.1).
13
* Rules for introducing new settings: If an element or attribute is introduced that was not
14
* present before VirtualBox 3.1, then settings version checks need to be introduced. The
15
* settings version for VirtualBox 3.1 is 1.9; see the SettingsVersion enumeration in
16
* src/VBox/Main/idl/VirtualBox.xidl for details about which version was used when.
18
* The settings versions checks are necessary because VirtualBox 3.1 no longer automatically
19
* converts XML settings files but only if necessary, that is, if settings are present that
20
* the old format does not support. If we write an element or attribute to a settings file
21
* of an older version, then an old VirtualBox (before 3.1) will attempt to validate it
22
* with XML schema, and that will certainly fail.
11
* 3.0) and 1.9 (used by VirtualBox 3.1) and newer ones obviously.
13
* The settings versions enum is defined in src/VBox/Main/idl/VirtualBox.xidl. To introduce
14
* a new settings version (should be necessary at most once per VirtualBox major release,
15
* if at all), add a new SettingsVersion value to that enum and grep for the previously
16
* highest value to see which code in here needs adjusting.
18
* Certainly ConfigFileBase::ConfigFileBase() will. Change VBOX_XML_VERSION below as well.
20
* Once a new settings version has been added, these are the rules for introducing a new
21
* setting: If an XML element or attribute or value is introduced that was not present in
22
* previous versions, then settings version checks need to be introduced. See the
23
* SettingsVersion enumeration in src/VBox/Main/idl/VirtualBox.xidl for details about which
24
* version was used when.
26
* The settings versions checks are necessary because since version 3.1, VirtualBox no longer
27
* automatically converts XML settings files but only if necessary, that is, if settings are
28
* present that the old format does not support. If we write an element or attribute to a
29
* settings file of an older version, then an old VirtualBox (before 3.1) will attempt to
30
* validate it with XML schema, and that will certainly fail.
24
32
* So, to introduce a new setting:
26
34
* 1) Make sure the constructor of corresponding settings structure has a proper default.
28
36
* 2) In the settings reader method, try to read the setting; if it's there, great, if not,
29
* the default value will have been set by the constructor.
31
* 3) In the settings writer method, write the setting _only_ if the current settings
32
* version (stored in m->sv) is high enough. That is, for VirtualBox 3.2, write it
33
* only if (m->sv >= SettingsVersion_v1_10).
35
* 4) In MachineConfigFile::bumpSettingsVersionIfNeeded(), check if the new setting has
37
* the default value will have been set by the constructor. The rule is to be tolerant
40
* 3) In MachineConfigFile::bumpSettingsVersionIfNeeded(), check if the new setting has
36
41
* a non-default value (i.e. that differs from the constructor). If so, bump the
37
* settings version to the current version so the settings writer (3) can write out
42
* settings version to the current version so the settings writer (4) can write out
38
43
* the non-default value properly.
40
45
* So far a corresponding method for MainConfigFile has not been necessary since there
41
46
* have been no incompatible changes yet.
48
* 4) In the settings writer method, write the setting _only_ if the current settings
49
* version (stored in m->sv) is high enough. That is, for VirtualBox 4.0, write it
50
* only if (m->sv >= SettingsVersion_v1_11).
543
* Reads a media registry entry from the main VirtualBox.xml file.
545
* Whereas the current media registry code is fairly straightforward, it was quite a mess
546
* with settings format before 1.4 (VirtualBox 2.0 used settings format 1.3). The elements
547
* in the media registry were much more inconsistent, and different elements were used
548
* depending on the type of device and image.
554
void ConfigFileBase::readMedium(MediaType t,
555
const xml::ElementNode &elmMedium, // HardDisk node if root; if recursing,
556
// child HardDisk node or DiffHardDisk node for pre-1.4
557
MediaList &llMedia) // list to append medium to (root disk or child list)
559
// <HardDisk uuid="{5471ecdb-1ddb-4012-a801-6d98e226868b}" location="/mnt/innotek-unix/vdis/Windows XP.vdi" format="VDI" type="Normal">
560
settings::Medium med;
562
if (!(elmMedium.getAttributeValue("uuid", strUUID)))
563
throw ConfigFileError(this, &elmMedium, N_("Required %s/@uuid attribute is missing"), elmMedium.getName());
565
parseUUID(med.uuid, strUUID);
567
bool fNeedsLocation = true;
571
if (m->sv < SettingsVersion_v1_4)
573
// here the system is:
574
// <HardDisk uuid="{....}" type="normal">
575
// <VirtualDiskImage filePath="/path/to/xxx.vdi"/>
578
fNeedsLocation = false;
579
bool fNeedsFilePath = true;
580
const xml::ElementNode *pelmImage;
581
if ((pelmImage = elmMedium.findChildElement("VirtualDiskImage")))
582
med.strFormat = "VDI";
583
else if ((pelmImage = elmMedium.findChildElement("VMDKImage")))
584
med.strFormat = "VMDK";
585
else if ((pelmImage = elmMedium.findChildElement("VHDImage")))
586
med.strFormat = "VHD";
587
else if ((pelmImage = elmMedium.findChildElement("ISCSIHardDisk")))
589
med.strFormat = "iSCSI";
591
fNeedsFilePath = false;
592
// location is special here: current settings specify an "iscsi://user@server:port/target/lun"
593
// string for the location and also have several disk properties for these, whereas this used
594
// to be hidden in several sub-elements before 1.4, so compose a location string and set up
596
med.strLocation = "iscsi://";
597
Utf8Str strUser, strServer, strPort, strTarget, strLun;
598
if (pelmImage->getAttributeValue("userName", strUser))
600
med.strLocation.append(strUser);
601
med.strLocation.append("@");
603
Utf8Str strServerAndPort;
604
if (pelmImage->getAttributeValue("server", strServer))
606
strServerAndPort = strServer;
608
if (pelmImage->getAttributeValue("port", strPort))
610
if (strServerAndPort.length())
611
strServerAndPort.append(":");
612
strServerAndPort.append(strPort);
614
med.strLocation.append(strServerAndPort);
615
if (pelmImage->getAttributeValue("target", strTarget))
617
med.strLocation.append("/");
618
med.strLocation.append(strTarget);
620
if (pelmImage->getAttributeValue("lun", strLun))
622
med.strLocation.append("/");
623
med.strLocation.append(strLun);
626
if (strServer.length() && strPort.length())
627
med.properties["TargetAddress"] = strServerAndPort;
628
if (strTarget.length())
629
med.properties["TargetName"] = strTarget;
630
if (strUser.length())
631
med.properties["InitiatorUsername"] = strUser;
633
if (pelmImage->getAttributeValue("password", strPassword))
634
med.properties["InitiatorSecret"] = strPassword;
636
med.properties["LUN"] = strLun;
638
else if ((pelmImage = elmMedium.findChildElement("CustomHardDisk")))
640
fNeedsFilePath = false;
641
fNeedsLocation = true;
642
// also requires @format attribute, which will be queried below
645
throw ConfigFileError(this, &elmMedium, N_("Required %s/VirtualDiskImage element is missing"), elmMedium.getName());
649
if (!(pelmImage->getAttributeValuePath("filePath", med.strLocation)))
650
throw ConfigFileError(this, &elmMedium, N_("Required %s/@filePath attribute is missing"), elmMedium.getName());
654
if (med.strFormat.isEmpty()) // not set with 1.4 format above, or 1.4 Custom format?
655
if (!(elmMedium.getAttributeValue("format", med.strFormat)))
656
throw ConfigFileError(this, &elmMedium, N_("Required %s/@format attribute is missing"), elmMedium.getName());
658
if (!(elmMedium.getAttributeValue("autoReset", med.fAutoReset)))
659
med.fAutoReset = false;
662
if ((elmMedium.getAttributeValue("type", strType)))
664
// pre-1.4 used lower case, so make this case-insensitive
666
if (strType == "NORMAL")
667
med.hdType = MediumType_Normal;
668
else if (strType == "IMMUTABLE")
669
med.hdType = MediumType_Immutable;
670
else if (strType == "WRITETHROUGH")
671
med.hdType = MediumType_Writethrough;
672
else if (strType == "SHAREABLE")
673
med.hdType = MediumType_Shareable;
674
else if (strType == "READONLY")
675
med.hdType = MediumType_Readonly;
676
else if (strType == "MULTIATTACH")
677
med.hdType = MediumType_MultiAttach;
679
throw ConfigFileError(this, &elmMedium, N_("HardDisk/@type attribute must be one of Normal, Immutable, Writethrough, Shareable, Readonly or MultiAttach"));
684
if (m->sv < SettingsVersion_v1_4)
686
// DVD and floppy images before 1.4 had "src" attribute instead of "location"
687
if (!(elmMedium.getAttributeValue("src", med.strLocation)))
688
throw ConfigFileError(this, &elmMedium, N_("Required %s/@src attribute is missing"), elmMedium.getName());
690
fNeedsLocation = false;
693
if (!(elmMedium.getAttributeValue("format", med.strFormat)))
695
// DVD and floppy images before 1.11 had no format attribute. assign the default.
696
med.strFormat = "RAW";
701
// current files and 1.4 CustomHardDisk elements must have a location attribute
702
if (!(elmMedium.getAttributeValue("location", med.strLocation)))
703
throw ConfigFileError(this, &elmMedium, N_("Required %s/@location attribute is missing"), elmMedium.getName());
705
elmMedium.getAttributeValue("Description", med.strDescription); // optional
707
// recurse to handle children
708
xml::NodesLoop nl2(elmMedium);
709
const xml::ElementNode *pelmHDChild;
710
while ((pelmHDChild = nl2.forAllNodes()))
713
&& ( pelmHDChild->nameEquals("HardDisk")
714
|| ( (m->sv < SettingsVersion_v1_4)
715
&& (pelmHDChild->nameEquals("DiffHardDisk"))
719
// recurse with this element and push the child onto our current children list
723
else if (pelmHDChild->nameEquals("Property"))
725
Utf8Str strPropName, strPropValue;
726
if ( (pelmHDChild->getAttributeValue("name", strPropName))
727
&& (pelmHDChild->getAttributeValue("value", strPropValue))
729
med.properties[strPropName] = strPropValue;
731
throw ConfigFileError(this, pelmHDChild, N_("Required HardDisk/Property/@name or @value attribute is missing"));
735
llMedia.push_back(med);
739
* Reads in the entire <MediaRegistry> chunk and stores its media in the lists
740
* of the given MediaRegistry structure.
742
* This is used in both MainConfigFile and MachineConfigFile since starting with
743
* VirtualBox 4.0, we can have media registries in both.
745
* For pre-1.4 files, this gets called with the <DiskRegistry> chunk instead.
747
* @param elmMediaRegistry
749
void ConfigFileBase::readMediaRegistry(const xml::ElementNode &elmMediaRegistry,
752
xml::NodesLoop nl1(elmMediaRegistry);
753
const xml::ElementNode *pelmChild1;
754
while ((pelmChild1 = nl1.forAllNodes()))
757
if (pelmChild1->nameEquals("HardDisks"))
759
else if (pelmChild1->nameEquals("DVDImages"))
761
else if (pelmChild1->nameEquals("FloppyImages"))
766
xml::NodesLoop nl2(*pelmChild1);
767
const xml::ElementNode *pelmMedium;
768
while ((pelmMedium = nl2.forAllNodes()))
771
&& (pelmMedium->nameEquals("HardDisk"))
775
mr.llHardDisks); // list to append hard disk data to: the root list
776
else if ( t == DVDImage
777
&& (pelmMedium->nameEquals("Image"))
781
mr.llDvdImages); // list to append dvd images to: the root list
782
else if ( t == FloppyImage
783
&& (pelmMedium->nameEquals("Image"))
787
mr.llFloppyImages); // list to append floppy images to: the root list
516
793
* Adds a "version" attribute to the given XML element with the
517
794
* VirtualBox settings version (e.g. "1.10-linux"). Used by
518
795
* the XML format for the root element and by the OVF export
987
* Creates a single <HardDisk> element for the given Medium structure
988
* and recurses to write the child hard disks underneath. Called from
989
* MainConfigFile::write().
995
void ConfigFileBase::buildMedium(xml::ElementNode &elmMedium,
996
DeviceType_T devType,
998
uint32_t level) // 0 for "root" call, incremented with each recursion
1000
xml::ElementNode *pelmMedium;
1002
if (devType == DeviceType_HardDisk)
1003
pelmMedium = elmMedium.createChild("HardDisk");
1005
pelmMedium = elmMedium.createChild("Image");
1007
pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
1009
pelmMedium->setAttributePath("location", mdm.strLocation);
1011
if (devType == DeviceType_HardDisk || RTStrICmp(mdm.strFormat.c_str(), "RAW"))
1012
pelmMedium->setAttribute("format", mdm.strFormat);
1014
pelmMedium->setAttribute("autoReset", mdm.fAutoReset);
1015
if (mdm.strDescription.length())
1016
pelmMedium->setAttribute("Description", mdm.strDescription);
1018
for (StringsMap::const_iterator it = mdm.properties.begin();
1019
it != mdm.properties.end();
1022
xml::ElementNode *pelmProp = pelmMedium->createChild("Property");
1023
pelmProp->setAttribute("name", it->first);
1024
pelmProp->setAttribute("value", it->second);
1027
// only for base hard disks, save the type
1030
const char *pcszType =
1031
mdm.hdType == MediumType_Normal ? "Normal" :
1032
mdm.hdType == MediumType_Immutable ? "Immutable" :
1033
mdm.hdType == MediumType_Writethrough ? "Writethrough" :
1034
mdm.hdType == MediumType_Shareable ? "Shareable" :
1035
mdm.hdType == MediumType_Readonly ? "Readonly" :
1036
mdm.hdType == MediumType_MultiAttach ? "MultiAttach" :
1038
// no need to save the usual DVD/floppy medium types
1039
if ( ( devType != DeviceType_DVD
1040
|| ( mdm.hdType != MediumType_Writethrough // shouldn't happen
1041
&& mdm.hdType != MediumType_Readonly))
1042
&& ( devType != DeviceType_Floppy
1043
|| mdm.hdType != MediumType_Writethrough))
1044
pelmMedium->setAttribute("type", pcszType);
1047
for (MediaList::const_iterator it = mdm.llChildren.begin();
1048
it != mdm.llChildren.end();
1051
// recurse for children
1052
buildMedium(*pelmMedium, // parent
1053
devType, // device type
1054
*it, // settings::Medium
1055
++level); // recursion level
1060
* Creates a <MediaRegistry> node under the given parent and writes out all
1061
* hard disks and DVD and floppy images from the lists in the given MediaRegistry
1062
* structure under it.
1064
* This is used in both MainConfigFile and MachineConfigFile since starting with
1065
* VirtualBox 4.0, we can have media registries in both.
1070
void ConfigFileBase::buildMediaRegistry(xml::ElementNode &elmParent,
1071
const MediaRegistry &mr)
1073
xml::ElementNode *pelmMediaRegistry = elmParent.createChild("MediaRegistry");
1075
xml::ElementNode *pelmHardDisks = pelmMediaRegistry->createChild("HardDisks");
1076
for (MediaList::const_iterator it = mr.llHardDisks.begin();
1077
it != mr.llHardDisks.end();
1080
buildMedium(*pelmHardDisks, DeviceType_HardDisk, *it, 0);
1083
xml::ElementNode *pelmDVDImages = pelmMediaRegistry->createChild("DVDImages");
1084
for (MediaList::const_iterator it = mr.llDvdImages.begin();
1085
it != mr.llDvdImages.end();
1088
buildMedium(*pelmDVDImages, DeviceType_DVD, *it, 0);
1091
xml::ElementNode *pelmFloppyImages = pelmMediaRegistry->createChild("FloppyImages");
1092
for (MediaList::const_iterator it = mr.llFloppyImages.begin();
1093
it != mr.llFloppyImages.end();
1096
buildMedium(*pelmFloppyImages, DeviceType_Floppy, *it, 0);
692
1101
* Cleans up memory allocated by the internal XML parser. To be called by
693
1102
* descendant classes when they're done analyzing the DOM tree to discard it.
787
* Reads a media registry entry from the main VirtualBox.xml file.
789
* Whereas the current media registry code is fairly straightforward, it was quite a mess
790
* with settings format before 1.4 (VirtualBox 2.0 used settings format 1.3). The elements
791
* in the media registry were much more inconsistent, and different elements were used
792
* depending on the type of device and image.
798
void MainConfigFile::readMedium(MediaType t,
799
const xml::ElementNode &elmMedium, // HardDisk node if root; if recursing,
800
// child HardDisk node or DiffHardDisk node for pre-1.4
801
MediaList &llMedia) // list to append medium to (root disk or child list)
803
// <HardDisk uuid="{5471ecdb-1ddb-4012-a801-6d98e226868b}" location="/mnt/innotek-unix/vdis/Windows XP.vdi" format="VDI" type="Normal">
804
settings::Medium med;
806
if (!(elmMedium.getAttributeValue("uuid", strUUID)))
807
throw ConfigFileError(this, &elmMedium, N_("Required %s/@uuid attribute is missing"), elmMedium.getName());
809
parseUUID(med.uuid, strUUID);
811
bool fNeedsLocation = true;
815
if (m->sv < SettingsVersion_v1_4)
817
// here the system is:
818
// <HardDisk uuid="{....}" type="normal">
819
// <VirtualDiskImage filePath="/path/to/xxx.vdi"/>
822
fNeedsLocation = false;
823
bool fNeedsFilePath = true;
824
const xml::ElementNode *pelmImage;
825
if ((pelmImage = elmMedium.findChildElement("VirtualDiskImage")))
826
med.strFormat = "VDI";
827
else if ((pelmImage = elmMedium.findChildElement("VMDKImage")))
828
med.strFormat = "VMDK";
829
else if ((pelmImage = elmMedium.findChildElement("VHDImage")))
830
med.strFormat = "VHD";
831
else if ((pelmImage = elmMedium.findChildElement("ISCSIHardDisk")))
833
med.strFormat = "iSCSI";
835
fNeedsFilePath = false;
836
// location is special here: current settings specify an "iscsi://user@server:port/target/lun"
837
// string for the location and also have several disk properties for these, whereas this used
838
// to be hidden in several sub-elements before 1.4, so compose a location string and set up
840
med.strLocation = "iscsi://";
841
Utf8Str strUser, strServer, strPort, strTarget, strLun;
842
if (pelmImage->getAttributeValue("userName", strUser))
844
med.strLocation.append(strUser);
845
med.strLocation.append("@");
847
Utf8Str strServerAndPort;
848
if (pelmImage->getAttributeValue("server", strServer))
850
strServerAndPort = strServer;
852
if (pelmImage->getAttributeValue("port", strPort))
854
if (strServerAndPort.length())
855
strServerAndPort.append(":");
856
strServerAndPort.append(strPort);
858
med.strLocation.append(strServerAndPort);
859
if (pelmImage->getAttributeValue("target", strTarget))
861
med.strLocation.append("/");
862
med.strLocation.append(strTarget);
864
if (pelmImage->getAttributeValue("lun", strLun))
866
med.strLocation.append("/");
867
med.strLocation.append(strLun);
870
if (strServer.length() && strPort.length())
871
med.properties["TargetAddress"] = strServerAndPort;
872
if (strTarget.length())
873
med.properties["TargetName"] = strTarget;
874
if (strUser.length())
875
med.properties["InitiatorUsername"] = strUser;
877
if (pelmImage->getAttributeValue("password", strPassword))
878
med.properties["InitiatorSecret"] = strPassword;
880
med.properties["LUN"] = strLun;
882
else if ((pelmImage = elmMedium.findChildElement("CustomHardDisk")))
884
fNeedsFilePath = false;
885
fNeedsLocation = true;
886
// also requires @format attribute, which will be queried below
889
throw ConfigFileError(this, &elmMedium, N_("Required %s/VirtualDiskImage element is missing"), elmMedium.getName());
892
if (!(pelmImage->getAttributeValue("filePath", med.strLocation)))
893
throw ConfigFileError(this, &elmMedium, N_("Required %s/@filePath attribute is missing"), elmMedium.getName());
896
if (med.strFormat.isEmpty()) // not set with 1.4 format above, or 1.4 Custom format?
897
if (!(elmMedium.getAttributeValue("format", med.strFormat)))
898
throw ConfigFileError(this, &elmMedium, N_("Required %s/@format attribute is missing"), elmMedium.getName());
900
if (!(elmMedium.getAttributeValue("autoReset", med.fAutoReset)))
901
med.fAutoReset = false;
904
if ((elmMedium.getAttributeValue("type", strType)))
906
// pre-1.4 used lower case, so make this case-insensitive
908
if (strType == "NORMAL")
909
med.hdType = MediumType_Normal;
910
else if (strType == "IMMUTABLE")
911
med.hdType = MediumType_Immutable;
912
else if (strType == "WRITETHROUGH")
913
med.hdType = MediumType_Writethrough;
914
else if (strType == "SHAREABLE")
915
med.hdType = MediumType_Shareable;
917
throw ConfigFileError(this, &elmMedium, N_("HardDisk/@type attribute must be one of Normal, Immutable or Writethrough"));
920
else if (m->sv < SettingsVersion_v1_4)
922
// DVD and floppy images before 1.4 had "src" attribute instead of "location"
923
if (!(elmMedium.getAttributeValue("src", med.strLocation)))
924
throw ConfigFileError(this, &elmMedium, N_("Required %s/@src attribute is missing"), elmMedium.getName());
926
fNeedsLocation = false;
930
// current files and 1.4 CustomHardDisk elements must have a location attribute
931
if (!(elmMedium.getAttributeValue("location", med.strLocation)))
932
throw ConfigFileError(this, &elmMedium, N_("Required %s/@location attribute is missing"), elmMedium.getName());
934
elmMedium.getAttributeValue("Description", med.strDescription); // optional
936
// recurse to handle children
937
xml::NodesLoop nl2(elmMedium);
938
const xml::ElementNode *pelmHDChild;
939
while ((pelmHDChild = nl2.forAllNodes()))
942
&& ( pelmHDChild->nameEquals("HardDisk")
943
|| ( (m->sv < SettingsVersion_v1_4)
944
&& (pelmHDChild->nameEquals("DiffHardDisk"))
948
// recurse with this element and push the child onto our current children list
952
else if (pelmHDChild->nameEquals("Property"))
954
Utf8Str strPropName, strPropValue;
955
if ( (pelmHDChild->getAttributeValue("name", strPropName))
956
&& (pelmHDChild->getAttributeValue("value", strPropValue))
958
med.properties[strPropName] = strPropValue;
960
throw ConfigFileError(this, pelmHDChild, N_("Required HardDisk/Property/@name or @value attribute is missing"));
964
llMedia.push_back(med);
968
* Reads in the entire <MediaRegistry> chunk. For pre-1.4 files, this gets called
969
* with the <DiskRegistry> chunk instead.
970
* @param elmMediaRegistry
972
void MainConfigFile::readMediaRegistry(const xml::ElementNode &elmMediaRegistry)
974
xml::NodesLoop nl1(elmMediaRegistry);
975
const xml::ElementNode *pelmChild1;
976
while ((pelmChild1 = nl1.forAllNodes()))
979
if (pelmChild1->nameEquals("HardDisks"))
981
else if (pelmChild1->nameEquals("DVDImages"))
983
else if (pelmChild1->nameEquals("FloppyImages"))
988
xml::NodesLoop nl2(*pelmChild1);
989
const xml::ElementNode *pelmMedium;
990
while ((pelmMedium = nl2.forAllNodes()))
993
&& (pelmMedium->nameEquals("HardDisk"))
997
llHardDisks); // list to append hard disk data to: the root list
998
else if ( t == DVDImage
999
&& (pelmMedium->nameEquals("Image"))
1003
llDvdImages); // list to append dvd images to: the root list
1004
else if ( t == FloppyImage
1005
&& (pelmMedium->nameEquals("Image"))
1009
llFloppyImages); // list to append floppy images to: the root list
1015
1196
* Reads in the <DHCPServers> chunk.
1016
1197
* @param elmDHCPServers
1137
* Creates a single <HardDisk> element for the given Medium structure
1138
* and recurses to write the child hard disks underneath. Called from
1139
* MainConfigFile::write().
1145
void MainConfigFile::writeHardDisk(xml::ElementNode &elmMedium,
1147
uint32_t level) // 0 for "root" call, incremented with each recursion
1149
xml::ElementNode *pelmHardDisk = elmMedium.createChild("HardDisk");
1150
pelmHardDisk->setAttribute("uuid", mdm.uuid.toStringCurly());
1151
pelmHardDisk->setAttribute("location", mdm.strLocation);
1152
pelmHardDisk->setAttribute("format", mdm.strFormat);
1154
pelmHardDisk->setAttribute("autoReset", mdm.fAutoReset);
1155
if (mdm.strDescription.length())
1156
pelmHardDisk->setAttribute("Description", mdm.strDescription);
1158
for (PropertiesMap::const_iterator it = mdm.properties.begin();
1159
it != mdm.properties.end();
1162
xml::ElementNode *pelmProp = pelmHardDisk->createChild("Property");
1163
pelmProp->setAttribute("name", it->first);
1164
pelmProp->setAttribute("value", it->second);
1167
// only for base hard disks, save the type
1170
const char *pcszType =
1171
mdm.hdType == MediumType_Normal ? "Normal" :
1172
mdm.hdType == MediumType_Immutable ? "Immutable" :
1173
mdm.hdType == MediumType_Writethrough ? "Writethrough" :
1174
mdm.hdType == MediumType_Shareable ? "Shareable" : "INVALID";
1175
pelmHardDisk->setAttribute("type", pcszType);
1178
for (MediaList::const_iterator it = mdm.llChildren.begin();
1179
it != mdm.llChildren.end();
1182
// recurse for children
1183
writeHardDisk(*pelmHardDisk, // parent
1184
*it, // settings::Medium
1185
++level); // recursion level
1190
1318
* Called from the IVirtualBox interface to write out VirtualBox.xml. This
1191
1319
* builds an XML DOM tree and writes it out to disk.
1211
1339
pelmMachineEntry->setAttribute("src", mre.strSettingsFile);
1214
xml::ElementNode *pelmMediaRegistry = pelmGlobal->createChild("MediaRegistry");
1216
xml::ElementNode *pelmHardDisks = pelmMediaRegistry->createChild("HardDisks");
1217
for (MediaList::const_iterator it = llHardDisks.begin();
1218
it != llHardDisks.end();
1221
writeHardDisk(*pelmHardDisks, *it, 0);
1224
xml::ElementNode *pelmDVDImages = pelmMediaRegistry->createChild("DVDImages");
1225
for (MediaList::const_iterator it = llDvdImages.begin();
1226
it != llDvdImages.end();
1229
const Medium &mdm = *it;
1230
xml::ElementNode *pelmMedium = pelmDVDImages->createChild("Image");
1231
pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
1232
pelmMedium->setAttribute("location", mdm.strLocation);
1233
if (mdm.strDescription.length())
1234
pelmMedium->setAttribute("Description", mdm.strDescription);
1237
xml::ElementNode *pelmFloppyImages = pelmMediaRegistry->createChild("FloppyImages");
1238
for (MediaList::const_iterator it = llFloppyImages.begin();
1239
it != llFloppyImages.end();
1242
const Medium &mdm = *it;
1243
xml::ElementNode *pelmMedium = pelmFloppyImages->createChild("Image");
1244
pelmMedium->setAttribute("uuid", mdm.uuid.toStringCurly());
1245
pelmMedium->setAttribute("location", mdm.strLocation);
1246
if (mdm.strDescription.length())
1247
pelmMedium->setAttribute("Description", mdm.strDescription);
1342
buildMediaRegistry(*pelmGlobal, mediaRegistry);
1250
1344
xml::ElementNode *pelmNetserviceRegistry = pelmGlobal->createChild("NetserviceRegistry");
1251
1345
xml::ElementNode *pelmDHCPServers = pelmNetserviceRegistry->createChild("DHCPServers");
2347
2479
// settings before 1.3 used lower case so make sure this is case-insensitive
2348
2480
strAuthType.toUpper();
2349
2481
if (strAuthType == "NULL")
2350
hw.vrdpSettings.authType = VRDPAuthType_Null;
2482
hw.vrdeSettings.authType = AuthType_Null;
2351
2483
else if (strAuthType == "GUEST")
2352
hw.vrdpSettings.authType = VRDPAuthType_Guest;
2484
hw.vrdeSettings.authType = AuthType_Guest;
2353
2485
else if (strAuthType == "EXTERNAL")
2354
hw.vrdpSettings.authType = VRDPAuthType_External;
2486
hw.vrdeSettings.authType = AuthType_External;
2356
2488
throw ConfigFileError(this, pelmHwChild, N_("Invalid value '%s' in RemoteDisplay/@authType attribute"), strAuthType.c_str());
2359
pelmHwChild->getAttributeValue("authTimeout", hw.vrdpSettings.ulAuthTimeout);
2360
pelmHwChild->getAttributeValue("allowMultiConnection", hw.vrdpSettings.fAllowMultiConnection);
2361
pelmHwChild->getAttributeValue("reuseSingleConnection", hw.vrdpSettings.fReuseSingleConnection);
2491
pelmHwChild->getAttributeValue("authLibrary", hw.vrdeSettings.strAuthLibrary);
2492
pelmHwChild->getAttributeValue("authTimeout", hw.vrdeSettings.ulAuthTimeout);
2493
pelmHwChild->getAttributeValue("allowMultiConnection", hw.vrdeSettings.fAllowMultiConnection);
2494
pelmHwChild->getAttributeValue("reuseSingleConnection", hw.vrdeSettings.fReuseSingleConnection);
2496
/* 3.2 and 4.0 betas, 4.0 has this information in VRDEProperties. */
2363
2497
const xml::ElementNode *pelmVideoChannel;
2364
2498
if ((pelmVideoChannel = pelmHwChild->findChildElement("VideoChannel")))
2366
pelmVideoChannel->getAttributeValue("enabled", hw.vrdpSettings.fVideoChannel);
2367
pelmVideoChannel->getAttributeValue("quality", hw.vrdpSettings.ulVideoChannelQuality);
2368
hw.vrdpSettings.ulVideoChannelQuality = RT_CLAMP(hw.vrdpSettings.ulVideoChannelQuality, 10, 100);
2500
bool fVideoChannel = false;
2501
pelmVideoChannel->getAttributeValue("enabled", fVideoChannel);
2502
hw.vrdeSettings.mapProperties["VideoChannel/Enabled"] = fVideoChannel? "true": "false";
2504
uint32_t ulVideoChannelQuality = 75;
2505
pelmVideoChannel->getAttributeValue("quality", ulVideoChannelQuality);
2506
ulVideoChannelQuality = RT_CLAMP(ulVideoChannelQuality, 10, 100);
2507
char *pszBuffer = NULL;
2508
if (RTStrAPrintf(&pszBuffer, "%d", ulVideoChannelQuality) >= 0)
2510
hw.vrdeSettings.mapProperties["VideoChannel/Quality"] = pszBuffer;
2511
RTStrFree(pszBuffer);
2514
hw.vrdeSettings.mapProperties["VideoChannel/Quality"] = "75";
2516
pelmHwChild->getAttributeValue("VRDEExtPack", hw.vrdeSettings.strVrdeExtPack);
2518
const xml::ElementNode *pelmProperties = pelmHwChild->findChildElement("VRDEProperties");
2519
if (pelmProperties != NULL)
2521
xml::NodesLoop nl(*pelmProperties);
2522
const xml::ElementNode *pelmProperty;
2523
while ((pelmProperty = nl.forAllNodes()))
2525
if (pelmProperty->nameEquals("Property"))
2527
/* <Property name="TCP/Ports" value="3000-3002"/> */
2528
Utf8Str strName, strValue;
2529
if ( ((pelmProperty->getAttributeValue("name", strName)))
2530
&& ((pelmProperty->getAttributeValue("value", strValue)))
2532
hw.vrdeSettings.mapProperties[strName] = strValue;
2534
throw ConfigFileError(this, pelmProperty, N_("Required VRDE Property/@name or @value attribute is missing"));
2371
2539
else if (pelmHwChild->nameEquals("BIOS"))
2977
3177
Utf8Str strUUID;
2978
3178
if ( (elmMachine.getAttributeValue("uuid", strUUID))
2979
&& (elmMachine.getAttributeValue("name", strName))
3179
&& (elmMachine.getAttributeValue("name", machineUserData.strName))
2982
3182
parseUUID(uuid, strUUID);
2984
if (!elmMachine.getAttributeValue("nameSync", fNameSync))
3184
elmMachine.getAttributeValue("nameSync", machineUserData.fNameSync);
2988
elmMachine.getAttributeValue("Description", strDescription);
3187
elmMachine.getAttributeValue("Description", machineUserData.strDescription);
2990
elmMachine.getAttributeValue("OSType", strOsType);
3189
elmMachine.getAttributeValue("OSType", machineUserData.strOsType);
2991
3190
if (m->sv < SettingsVersion_v1_5)
2992
convertOldOSType_pre1_5(strOsType);
2994
elmMachine.getAttributeValue("stateFile", strStateFile);
3191
convertOldOSType_pre1_5(machineUserData.strOsType);
3193
elmMachine.getAttributeValuePath("stateFile", strStateFile);
2995
3195
if (elmMachine.getAttributeValue("currentSnapshot", str))
2996
3196
parseUUID(uuidCurrentSnapshot, str);
2997
elmMachine.getAttributeValue("snapshotFolder", strSnapshotFolder);
3198
elmMachine.getAttributeValuePath("snapshotFolder", machineUserData.strSnapshotFolder);
2998
3200
if (!elmMachine.getAttributeValue("currentStateModified", fCurrentStateModified))
2999
3201
fCurrentStateModified = true;
3000
3202
if (elmMachine.getAttributeValue("lastStateChange", str))
3030
3232
llFirstSnapshot.push_back(snap);
3032
3234
else if (pelmMachineChild->nameEquals("Description"))
3033
strDescription = pelmMachineChild->getValue();
3235
machineUserData.strDescription = pelmMachineChild->getValue();
3034
3236
else if (pelmMachineChild->nameEquals("Teleporter"))
3036
if (!pelmMachineChild->getAttributeValue("enabled", fTeleporterEnabled))
3037
fTeleporterEnabled = false;
3038
if (!pelmMachineChild->getAttributeValue("port", uTeleporterPort))
3039
uTeleporterPort = 0;
3040
if (!pelmMachineChild->getAttributeValue("address", strTeleporterAddress))
3041
strTeleporterAddress = "";
3042
if (!pelmMachineChild->getAttributeValue("password", strTeleporterPassword))
3043
strTeleporterPassword = "";
3238
pelmMachineChild->getAttributeValue("enabled", machineUserData.fTeleporterEnabled);
3239
pelmMachineChild->getAttributeValue("port", machineUserData.uTeleporterPort);
3240
pelmMachineChild->getAttributeValue("address", machineUserData.strTeleporterAddress);
3241
pelmMachineChild->getAttributeValue("password", machineUserData.strTeleporterPassword);
3243
else if (pelmMachineChild->nameEquals("FaultTolerance"))
3245
Utf8Str strFaultToleranceSate;
3246
if (pelmMachineChild->getAttributeValue("state", strFaultToleranceSate))
3248
if (strFaultToleranceSate == "master")
3249
machineUserData.enmFaultToleranceState = FaultToleranceState_Master;
3251
if (strFaultToleranceSate == "standby")
3252
machineUserData.enmFaultToleranceState = FaultToleranceState_Standby;
3254
machineUserData.enmFaultToleranceState = FaultToleranceState_Inactive;
3256
pelmMachineChild->getAttributeValue("port", machineUserData.uFaultTolerancePort);
3257
pelmMachineChild->getAttributeValue("address", machineUserData.strFaultToleranceAddress);
3258
pelmMachineChild->getAttributeValue("interval", machineUserData.uFaultToleranceInterval);
3259
pelmMachineChild->getAttributeValue("password", machineUserData.strFaultTolerancePassword);
3261
else if (pelmMachineChild->nameEquals("MediaRegistry"))
3262
readMediaRegistry(*pelmMachineChild, mediaRegistry);
3047
3265
if (m->sv < SettingsVersion_v1_9)
3222
3457
if (m->sv >= SettingsVersion_v1_8)
3223
3458
pelmDisplay->setAttribute("accelerate2DVideo", hw.fAccelerate2DVideo);
3225
xml::ElementNode *pelmVRDP = pelmHardware->createChild("RemoteDisplay");
3226
pelmVRDP->setAttribute("enabled", hw.vrdpSettings.fEnabled);
3227
Utf8Str strPort = hw.vrdpSettings.strPort;
3228
if (!strPort.length())
3230
pelmVRDP->setAttribute("port", strPort);
3231
if (hw.vrdpSettings.strNetAddress.length())
3232
pelmVRDP->setAttribute("netAddress", hw.vrdpSettings.strNetAddress);
3460
xml::ElementNode *pelmVRDE = pelmHardware->createChild("RemoteDisplay");
3461
pelmVRDE->setAttribute("enabled", hw.vrdeSettings.fEnabled);
3462
if (m->sv < SettingsVersion_v1_11)
3464
/* In VBox 4.0 these attributes are replaced with "Properties". */
3466
StringsMap::const_iterator it = hw.vrdeSettings.mapProperties.find("TCP/Ports");
3467
if (it != hw.vrdeSettings.mapProperties.end())
3468
strPort = it->second;
3469
if (!strPort.length())
3471
pelmVRDE->setAttribute("port", strPort);
3474
it = hw.vrdeSettings.mapProperties.find("TCP/Address");
3475
if (it != hw.vrdeSettings.mapProperties.end())
3476
strAddress = it->second;
3477
if (strAddress.length())
3478
pelmVRDE->setAttribute("netAddress", strAddress);
3233
3480
const char *pcszAuthType;
3234
switch (hw.vrdpSettings.authType)
3236
case VRDPAuthType_Guest: pcszAuthType = "Guest"; break;
3237
case VRDPAuthType_External: pcszAuthType = "External"; break;
3238
default: /*case VRDPAuthType_Null:*/ pcszAuthType = "Null"; break;
3240
pelmVRDP->setAttribute("authType", pcszAuthType);
3242
if (hw.vrdpSettings.ulAuthTimeout != 0)
3243
pelmVRDP->setAttribute("authTimeout", hw.vrdpSettings.ulAuthTimeout);
3244
if (hw.vrdpSettings.fAllowMultiConnection)
3245
pelmVRDP->setAttribute("allowMultiConnection", hw.vrdpSettings.fAllowMultiConnection);
3246
if (hw.vrdpSettings.fReuseSingleConnection)
3247
pelmVRDP->setAttribute("reuseSingleConnection", hw.vrdpSettings.fReuseSingleConnection);
3249
if (m->sv >= SettingsVersion_v1_10)
3251
xml::ElementNode *pelmVideoChannel = pelmVRDP->createChild("VideoChannel");
3252
pelmVideoChannel->setAttribute("enabled", hw.vrdpSettings.fVideoChannel);
3253
pelmVideoChannel->setAttribute("quality", hw.vrdpSettings.ulVideoChannelQuality);
3481
switch (hw.vrdeSettings.authType)
3483
case AuthType_Guest: pcszAuthType = "Guest"; break;
3484
case AuthType_External: pcszAuthType = "External"; break;
3485
default: /*case AuthType_Null:*/ pcszAuthType = "Null"; break;
3487
pelmVRDE->setAttribute("authType", pcszAuthType);
3489
if (hw.vrdeSettings.ulAuthTimeout != 0)
3490
pelmVRDE->setAttribute("authTimeout", hw.vrdeSettings.ulAuthTimeout);
3491
if (hw.vrdeSettings.fAllowMultiConnection)
3492
pelmVRDE->setAttribute("allowMultiConnection", hw.vrdeSettings.fAllowMultiConnection);
3493
if (hw.vrdeSettings.fReuseSingleConnection)
3494
pelmVRDE->setAttribute("reuseSingleConnection", hw.vrdeSettings.fReuseSingleConnection);
3496
if (m->sv == SettingsVersion_v1_10)
3498
xml::ElementNode *pelmVideoChannel = pelmVRDE->createChild("VideoChannel");
3500
/* In 4.0 videochannel settings were replaced with properties, so look at properties. */
3502
StringsMap::const_iterator it = hw.vrdeSettings.mapProperties.find("VideoChannel/Enabled");
3503
if (it != hw.vrdeSettings.mapProperties.end())
3505
bool fVideoChannel = RTStrICmp(str.c_str(), "true") == 0
3506
|| RTStrCmp(str.c_str(), "1") == 0;
3507
pelmVideoChannel->setAttribute("enabled", fVideoChannel);
3509
it = hw.vrdeSettings.mapProperties.find("VideoChannel/Quality");
3510
if (it != hw.vrdeSettings.mapProperties.end())
3512
uint32_t ulVideoChannelQuality = RTStrToUInt32(str.c_str()); /* This returns 0 on invalid string which is ok. */
3513
if (ulVideoChannelQuality == 0)
3514
ulVideoChannelQuality = 75;
3516
ulVideoChannelQuality = RT_CLAMP(ulVideoChannelQuality, 10, 100);
3517
pelmVideoChannel->setAttribute("quality", ulVideoChannelQuality);
3519
if (m->sv >= SettingsVersion_v1_11)
3521
if (hw.vrdeSettings.strAuthLibrary.length())
3522
pelmVRDE->setAttribute("authLibrary", hw.vrdeSettings.strAuthLibrary);
3523
if (hw.vrdeSettings.strVrdeExtPack.isNotEmpty())
3524
pelmVRDE->setAttribute("VRDEExtPack", hw.vrdeSettings.strVrdeExtPack);
3525
if (hw.vrdeSettings.mapProperties.size() > 0)
3527
xml::ElementNode *pelmProperties = pelmVRDE->createChild("VRDEProperties");
3528
for (StringsMap::const_iterator it = hw.vrdeSettings.mapProperties.begin();
3529
it != hw.vrdeSettings.mapProperties.end();
3532
const Utf8Str &strName = it->first;
3533
const Utf8Str &strValue = it->second;
3534
xml::ElementNode *pelm = pelmProperties->createChild("Property");
3535
pelm->setAttribute("name", strName);
3536
pelm->setAttribute("value", strValue);
3256
3541
xml::ElementNode *pelmBIOS = pelmHardware->createChild("BIOS");
3884
4222
setVersionAttribute(elmMachine);
3886
4224
elmMachine.setAttribute("uuid", uuid.toStringCurly());
3887
elmMachine.setAttribute("name", strName);
3889
elmMachine.setAttribute("nameSync", fNameSync);
3890
if (strDescription.length())
3891
elmMachine.createChild("Description")->addContent(strDescription);
3892
elmMachine.setAttribute("OSType", strOsType);
3893
if (strStateFile.length())
3894
elmMachine.setAttribute("stateFile", strStateFile);
4225
elmMachine.setAttribute("name", machineUserData.strName);
4226
if (!machineUserData.fNameSync)
4227
elmMachine.setAttribute("nameSync", machineUserData.fNameSync);
4228
if (machineUserData.strDescription.length())
4229
elmMachine.createChild("Description")->addContent(machineUserData.strDescription);
4230
elmMachine.setAttribute("OSType", machineUserData.strOsType);
4231
if ( strStateFile.length()
4232
&& !(fl & BuildMachineXML_SuppressSavedState)
4234
elmMachine.setAttributePath("stateFile", strStateFile);
3895
4235
if ( (fl & BuildMachineXML_IncludeSnapshots)
3896
4236
&& !uuidCurrentSnapshot.isEmpty())
3897
4237
elmMachine.setAttribute("currentSnapshot", uuidCurrentSnapshot.toStringCurly());
3898
if (strSnapshotFolder.length())
3899
elmMachine.setAttribute("snapshotFolder", strSnapshotFolder);
4239
if (machineUserData.strSnapshotFolder.length())
4240
elmMachine.setAttributePath("snapshotFolder", machineUserData.strSnapshotFolder);
3900
4241
if (!fCurrentStateModified)
3901
4242
elmMachine.setAttribute("currentStateModified", fCurrentStateModified);
3902
4243
elmMachine.setAttribute("lastStateChange", makeString(timeLastStateChange));
3904
4245
elmMachine.setAttribute("aborted", fAborted);
3905
4246
if ( m->sv >= SettingsVersion_v1_9
3906
&& ( fTeleporterEnabled
3908
|| !strTeleporterAddress.isEmpty()
3909
|| !strTeleporterPassword.isEmpty()
4247
&& ( machineUserData.fTeleporterEnabled
4248
|| machineUserData.uTeleporterPort
4249
|| !machineUserData.strTeleporterAddress.isEmpty()
4250
|| !machineUserData.strTeleporterPassword.isEmpty()
3913
4254
xml::ElementNode *pelmTeleporter = elmMachine.createChild("Teleporter");
3914
pelmTeleporter->setAttribute("enabled", fTeleporterEnabled);
3915
pelmTeleporter->setAttribute("port", uTeleporterPort);
3916
pelmTeleporter->setAttribute("address", strTeleporterAddress);
3917
pelmTeleporter->setAttribute("password", strTeleporterPassword);
3920
writeExtraData(elmMachine, mapExtraDataItems);
4255
pelmTeleporter->setAttribute("enabled", machineUserData.fTeleporterEnabled);
4256
pelmTeleporter->setAttribute("port", machineUserData.uTeleporterPort);
4257
pelmTeleporter->setAttribute("address", machineUserData.strTeleporterAddress);
4258
pelmTeleporter->setAttribute("password", machineUserData.strTeleporterPassword);
4261
if ( m->sv >= SettingsVersion_v1_11
4262
&& ( machineUserData.enmFaultToleranceState != FaultToleranceState_Inactive
4263
|| machineUserData.uFaultTolerancePort
4264
|| machineUserData.uFaultToleranceInterval
4265
|| !machineUserData.strFaultToleranceAddress.isEmpty()
4269
xml::ElementNode *pelmFaultTolerance = elmMachine.createChild("FaultTolerance");
4270
switch (machineUserData.enmFaultToleranceState)
4272
case FaultToleranceState_Inactive:
4273
pelmFaultTolerance->setAttribute("state", "inactive");
4275
case FaultToleranceState_Master:
4276
pelmFaultTolerance->setAttribute("state", "master");
4278
case FaultToleranceState_Standby:
4279
pelmFaultTolerance->setAttribute("state", "standby");
4283
pelmFaultTolerance->setAttribute("port", machineUserData.uFaultTolerancePort);
4284
pelmFaultTolerance->setAttribute("address", machineUserData.strFaultToleranceAddress);
4285
pelmFaultTolerance->setAttribute("interval", machineUserData.uFaultToleranceInterval);
4286
pelmFaultTolerance->setAttribute("password", machineUserData.strFaultTolerancePassword);
4289
if ( (fl & BuildMachineXML_MediaRegistry)
4290
&& (m->sv >= SettingsVersion_v1_11)
4292
buildMediaRegistry(elmMachine, mediaRegistry);
4294
buildExtraData(elmMachine, mapExtraDataItems);
3922
4296
if ( (fl & BuildMachineXML_IncludeSnapshots)
3923
4297
&& llFirstSnapshot.size())
4037
4411
* This adjusts the settings version in m->sv if incompatible settings require
4038
4412
* a settings bump, whereas otherwise we try to preserve the settings version
4039
4413
* to avoid breaking compatibility with older versions.
4415
* We do the checks in here in reverse order: newest first, oldest last, so
4416
* that we avoid unnecessary checks since some of these are expensive.
4041
4418
void MachineConfigFile::bumpSettingsVersionIfNeeded()
4043
// The hardware versions other than "1" requires settings version 1.4 (2.1+).
4044
if ( m->sv < SettingsVersion_v1_4
4045
&& hardwareMachine.strVersion != "1"
4047
m->sv = SettingsVersion_v1_4;
4049
// "accelerate 2d video" requires settings version 1.8
4050
if ( (m->sv < SettingsVersion_v1_8)
4051
&& (hardwareMachine.fAccelerate2DVideo)
4053
m->sv = SettingsVersion_v1_8;
4055
// all the following require settings version 1.9
4056
if ( (m->sv < SettingsVersion_v1_9)
4057
&& ( (hardwareMachine.firmwareType >= FirmwareType_EFI)
4058
|| (hardwareMachine.fHardwareVirtExclusive != HWVIRTEXCLUSIVEDEFAULT)
4059
|| fTeleporterEnabled
4061
|| !strTeleporterAddress.isEmpty()
4062
|| !strTeleporterPassword.isEmpty()
4063
|| !hardwareMachine.uuid.isEmpty()
4066
m->sv = SettingsVersion_v1_9;
4068
// settings version 1.9 is also required if there is not exactly one DVD
4420
if (m->sv < SettingsVersion_v1_11)
4422
// VirtualBox 4.0 adds HD audio, CPU priorities, fault tolerance,
4423
// per-machine media registries, VRDE, JRockitVE and bandwidth gorups.
4424
if ( hardwareMachine.audioAdapter.controllerType == AudioControllerType_HDA
4425
|| hardwareMachine.ulCpuExecutionCap != 100
4426
|| machineUserData.enmFaultToleranceState != FaultToleranceState_Inactive
4427
|| machineUserData.uFaultTolerancePort
4428
|| machineUserData.uFaultToleranceInterval
4429
|| !machineUserData.strFaultToleranceAddress.isEmpty()
4430
|| mediaRegistry.llHardDisks.size()
4431
|| mediaRegistry.llDvdImages.size()
4432
|| mediaRegistry.llFloppyImages.size()
4433
|| !hardwareMachine.vrdeSettings.strVrdeExtPack.isEmpty()
4434
|| !hardwareMachine.vrdeSettings.strAuthLibrary.isEmpty()
4435
|| machineUserData.strOsType == "JRockitVE"
4436
|| hardwareMachine.ioSettings.llBandwidthGroups.size()
4438
m->sv = SettingsVersion_v1_11;
4441
if (m->sv < SettingsVersion_v1_10)
4443
/* If the properties contain elements other than "TCP/Ports" and "TCP/Address",
4444
* then increase the version to at least VBox 3.2, which can have video channel properties.
4446
unsigned cOldProperties = 0;
4448
StringsMap::const_iterator it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Ports");
4449
if (it != hardwareMachine.vrdeSettings.mapProperties.end())
4451
it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Address");
4452
if (it != hardwareMachine.vrdeSettings.mapProperties.end())
4455
if (hardwareMachine.vrdeSettings.mapProperties.size() != cOldProperties)
4456
m->sv = SettingsVersion_v1_10;
4459
if (m->sv < SettingsVersion_v1_11)
4461
/* If the properties contain elements other than "TCP/Ports", "TCP/Address",
4462
* "VideoChannel/Enabled" and "VideoChannel/Quality" then increase the version to VBox 4.0.
4464
unsigned cOldProperties = 0;
4466
StringsMap::const_iterator it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Ports");
4467
if (it != hardwareMachine.vrdeSettings.mapProperties.end())
4469
it = hardwareMachine.vrdeSettings.mapProperties.find("TCP/Address");
4470
if (it != hardwareMachine.vrdeSettings.mapProperties.end())
4472
it = hardwareMachine.vrdeSettings.mapProperties.find("VideoChannel/Enabled");
4473
if (it != hardwareMachine.vrdeSettings.mapProperties.end())
4475
it = hardwareMachine.vrdeSettings.mapProperties.find("VideoChannel/Quality");
4476
if (it != hardwareMachine.vrdeSettings.mapProperties.end())
4479
if (hardwareMachine.vrdeSettings.mapProperties.size() != cOldProperties)
4480
m->sv = SettingsVersion_v1_11;
4483
// settings version 1.9 is required if there is not exactly one DVD
4069
4484
// or more than one floppy drive present or the DVD is not at the secondary
4070
4485
// master; this check is a bit more complicated
4072
4487
// settings version 1.10 is required if the host cache should be disabled
4073
if (m->sv < SettingsVersion_v1_10)
4489
// settings version 1.11 is required for bandwidth limits and if more than
4490
// one controller of each type is present.
4491
if (m->sv < SettingsVersion_v1_11)
4493
// count attached DVDs and floppies (only if < v1.9)
4075
4494
size_t cDVDs = 0;
4076
4495
size_t cFloppies = 0;
4078
// need to run thru all the storage controllers to figure this out
4497
// count storage controllers (if < v1.11)
4499
size_t cScsiLsi = 0;
4500
size_t cScsiBuslogic = 0;
4505
// need to run thru all the storage controllers and attached devices to figure this out
4079
4506
for (StorageControllersList::const_iterator it = storageMachine.llStorageControllers.begin();
4080
4507
it != storageMachine.llStorageControllers.end();
4083
4510
const StorageController &sctl = *it;
4512
// count storage controllers of each type; 1.11 is required if more than one
4513
// controller of one type is present
4514
switch (sctl.storageBus)
4516
case StorageBus_IDE:
4519
case StorageBus_SATA:
4522
case StorageBus_SAS:
4525
case StorageBus_SCSI:
4526
if (sctl.controllerType == StorageControllerType_LsiLogic)
4531
case StorageBus_Floppy:
4541
|| cScsiBuslogic > 1
4546
m->sv = SettingsVersion_v1_11;
4547
break; // abort the loop -- we will not raise the version further
4084
4550
for (AttachedDevicesList::const_iterator it2 = sctl.llAttachedDevices.begin();
4085
4551
it2 != sctl.llAttachedDevices.end();
4554
const AttachedDevice &att = *it2;
4556
// Bandwidth limitations are new in VirtualBox 4.0 (1.11)
4557
if (m->sv < SettingsVersion_v1_11)
4559
if (att.strBwGroup.length() != 0)
4561
m->sv = SettingsVersion_v1_11;
4562
break; // abort the loop -- we will not raise the version further
4566
// disabling the host IO cache requires settings version 1.10
4567
if ( (m->sv < SettingsVersion_v1_10)
4568
&& (!sctl.fUseHostIOCache)
4570
m->sv = SettingsVersion_v1_10;
4088
4572
// we can only write the StorageController/@Instance attribute with v1.9
4089
if (sctl.ulInstance != 0)
4091
if (m->sv < SettingsVersion_v1_9)
4092
m->sv = SettingsVersion_v1_9;
4573
if ( (m->sv < SettingsVersion_v1_9)
4574
&& (sctl.ulInstance != 0)
4576
m->sv = SettingsVersion_v1_9;
4095
const AttachedDevice &att = *it2;
4096
if (att.deviceType == DeviceType_DVD)
4578
if (m->sv < SettingsVersion_v1_9)
4098
if ( (sctl.storageBus != StorageBus_IDE) // DVD at bus other than DVD?
4099
|| (att.lPort != 1) // DVDs not at secondary master?
4100
|| (att.lDevice != 0)
4580
if (att.deviceType == DeviceType_DVD)
4103
if (m->sv < SettingsVersion_v1_9)
4582
if ( (sctl.storageBus != StorageBus_IDE) // DVD at bus other than DVD?
4583
|| (att.lPort != 1) // DVDs not at secondary master?
4584
|| (att.lDevice != 0)
4104
4586
m->sv = SettingsVersion_v1_9;
4109
else if (att.deviceType == DeviceType_Floppy)
4112
// Disabling the host IO cache requires settings version 1.10
4113
if (!sctl.fUseHostIOCache)
4115
m->sv = SettingsVersion_v1_10;
4116
break; /* abort the loop -- we will not raise the version further */
4590
else if (att.deviceType == DeviceType_Floppy)
4595
if (m->sv >= SettingsVersion_v1_11)
4596
break; // abort the loop -- we will not raise the version further
4121
4599
// VirtualBox before 3.1 had zero or one floppy and exactly one DVD,
4128
4606
m->sv = SettingsVersion_v1_9;
4131
// VirtualBox 3.2 adds support for CPU hotplug, RTC timezone control, HID type and HPET
4132
if ( m->sv < SettingsVersion_v1_10
4134
|| hardwareMachine.fCpuHotPlug
4135
|| hardwareMachine.pointingHidType != PointingHidType_PS2Mouse
4136
|| hardwareMachine.keyboardHidType != KeyboardHidType_PS2Keyboard
4137
|| hardwareMachine.fHpetEnabled
4140
m->sv = SettingsVersion_v1_10;
4142
// VirtualBox 3.2 adds support for page fusion
4143
if ( m->sv < SettingsVersion_v1_10
4144
&& hardwareMachine.fPageFusionEnabled
4146
m->sv = SettingsVersion_v1_10;
4148
// VirtualBox 3.2 adds NAT and boot priority to the NIC config in Main.
4609
// VirtualBox 3.2: Check for non default I/O settings
4610
if (m->sv < SettingsVersion_v1_10)
4612
if ( (hardwareMachine.ioSettings.fIoCacheEnabled != true)
4613
|| (hardwareMachine.ioSettings.ulIoCacheSize != 5)
4615
|| (hardwareMachine.fPageFusionEnabled)
4616
// and CPU hotplug, RTC timezone control, HID type and HPET
4617
|| machineUserData.fRTCUseUTC
4618
|| hardwareMachine.fCpuHotPlug
4619
|| hardwareMachine.pointingHidType != PointingHidType_PS2Mouse
4620
|| hardwareMachine.keyboardHidType != KeyboardHidType_PS2Keyboard
4621
|| hardwareMachine.fHpetEnabled
4623
m->sv = SettingsVersion_v1_10;
4626
// VirtualBox 3.2 adds NAT and boot priority to the NIC config in Main
4149
4627
if (m->sv < SettingsVersion_v1_10)
4151
4629
NetworkAdaptersList::const_iterator netit;
4152
4630
for (netit = hardwareMachine.llNetworkAdapters.begin();
4153
netit != hardwareMachine.llNetworkAdapters.end(); ++netit)
4631
netit != hardwareMachine.llNetworkAdapters.end();
4155
if ( netit->fEnabled
4156
&& netit->mode == NetworkAttachmentType_NAT
4157
&& ( netit->nat.u32Mtu != 0
4158
|| netit->nat.u32SockRcv != 0
4159
|| netit->nat.u32SockSnd != 0
4160
|| netit->nat.u32TcpRcv != 0
4161
|| netit->nat.u32TcpSnd != 0
4162
|| !netit->nat.fDnsPassDomain
4163
|| netit->nat.fDnsProxy
4164
|| netit->nat.fDnsUseHostResolver
4165
|| netit->nat.fAliasLog
4166
|| netit->nat.fAliasProxyOnly
4167
|| netit->nat.fAliasUseSamePorts
4168
|| netit->nat.strTftpPrefix.length()
4169
|| netit->nat.strTftpBootFile.length()
4170
|| netit->nat.strTftpNextServer.length()
4171
|| netit->nat.llRules.size())
4174
m->sv = SettingsVersion_v1_10;
4177
if ( netit->fEnabled
4178
&& netit->ulBootPriority != 0)
4180
m->sv = SettingsVersion_v1_10;
4634
if ( (m->sv < SettingsVersion_v1_11)
4635
&& (netit->ulBandwidthLimit)
4638
/* New in VirtualBox 4.0 */
4639
m->sv = SettingsVersion_v1_11;
4642
else if ( (m->sv < SettingsVersion_v1_10)
4643
&& (netit->fEnabled)
4644
&& (netit->mode == NetworkAttachmentType_NAT)
4645
&& ( netit->nat.u32Mtu != 0
4646
|| netit->nat.u32SockRcv != 0
4647
|| netit->nat.u32SockSnd != 0
4648
|| netit->nat.u32TcpRcv != 0
4649
|| netit->nat.u32TcpSnd != 0
4650
|| !netit->nat.fDnsPassDomain
4651
|| netit->nat.fDnsProxy
4652
|| netit->nat.fDnsUseHostResolver
4653
|| netit->nat.fAliasLog
4654
|| netit->nat.fAliasProxyOnly
4655
|| netit->nat.fAliasUseSamePorts
4656
|| netit->nat.strTftpPrefix.length()
4657
|| netit->nat.strTftpBootFile.length()
4658
|| netit->nat.strTftpNextServer.length()
4659
|| netit->nat.llRules.size()
4663
m->sv = SettingsVersion_v1_10;
4664
// no break because we still might need v1.11 above
4666
else if ( (m->sv < SettingsVersion_v1_10)
4667
&& (netit->fEnabled)
4668
&& (netit->ulBootPriority != 0)
4671
m->sv = SettingsVersion_v1_10;
4672
// no break because we still might need v1.11 above
4185
// Check for non default I/O settings and bump the settings version.
4186
if (m->sv < SettingsVersion_v1_10)
4188
if ( hardwareMachine.ioSettings.fIoCacheEnabled != true
4189
|| hardwareMachine.ioSettings.ulIoCacheSize != 5
4190
|| hardwareMachine.ioSettings.ulIoBandwidthMax != 0)
4191
m->sv = SettingsVersion_v1_10;
4194
// VirtualBox 3.2 adds support for VRDP video channel
4195
if ( m->sv < SettingsVersion_v1_10
4196
&& ( hardwareMachine.vrdpSettings.fVideoChannel
4677
// all the following require settings version 1.9
4678
if ( (m->sv < SettingsVersion_v1_9)
4679
&& ( (hardwareMachine.firmwareType >= FirmwareType_EFI)
4680
|| (hardwareMachine.fHardwareVirtExclusive != HWVIRTEXCLUSIVEDEFAULT)
4681
|| machineUserData.fTeleporterEnabled
4682
|| machineUserData.uTeleporterPort
4683
|| !machineUserData.strTeleporterAddress.isEmpty()
4684
|| !machineUserData.strTeleporterPassword.isEmpty()
4685
|| !hardwareMachine.uuid.isEmpty()
4199
m->sv = SettingsVersion_v1_10;
4688
m->sv = SettingsVersion_v1_9;
4690
// "accelerate 2d video" requires settings version 1.8
4691
if ( (m->sv < SettingsVersion_v1_8)
4692
&& (hardwareMachine.fAccelerate2DVideo)
4694
m->sv = SettingsVersion_v1_8;
4696
// The hardware versions other than "1" requires settings version 1.4 (2.1+).
4697
if ( m->sv < SettingsVersion_v1_4
4698
&& hardwareMachine.strVersion != "1"
4700
m->sv = SettingsVersion_v1_4;