- Timestamp:
- Jan 28, 2022 4:09:52 PM (3 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageAppliance.cpp
r93115 r93480 121 121 122 122 return rc; 123 } 124 125 /** 126 * Helper routine to parse the ExtraData Utf8Str for a storage controller's 127 * value or channel value. 128 * 129 * @param aExtraData The ExtraData string which can have a format of 130 * either 'controller=13;channel=3' or '11'. 131 * @param pszKey The string being looked up, usually either 'controller' 132 * or 'channel' but can be NULL or empty. 133 * @param puVal The integer value of the 'controller=' or 'channel=' 134 * key (or the controller number when there is no key) in 135 * the ExtraData string. 136 * @returns COM status code. 137 */ 138 static int getStorageControllerDetailsFromStr(const com::Utf8Str &aExtraData, const char *pszKey, uint32_t *puVal) 139 { 140 int vrc; 141 142 if (pszKey && *pszKey) 143 { 144 size_t posKey = aExtraData.find(pszKey); 145 if (posKey == Utf8Str::npos) 146 return VERR_INVALID_PARAMETER; 147 vrc = RTStrToUInt32Ex(aExtraData.c_str() + posKey + strlen(pszKey), NULL, 0, puVal); 148 } 149 else 150 { 151 vrc = RTStrToUInt32Ex(aExtraData.c_str(), NULL, 0, puVal); 152 } 153 154 if (vrc == VWRN_NUMBER_TOO_BIG || vrc == VWRN_NEGATIVE_UNSIGNED) 155 return VERR_INVALID_PARAMETER; 156 157 return vrc; 158 } 159 160 static bool isStorageControllerType(VirtualSystemDescriptionType_T avsdType) 161 { 162 switch (avsdType) 163 { 164 case VirtualSystemDescriptionType_HardDiskControllerIDE: 165 case VirtualSystemDescriptionType_HardDiskControllerSATA: 166 case VirtualSystemDescriptionType_HardDiskControllerSCSI: 167 case VirtualSystemDescriptionType_HardDiskControllerSAS: 168 case VirtualSystemDescriptionType_HardDiskControllerVirtioSCSI: 169 return true; 170 default: 171 return false; 172 } 123 173 } 124 174 … … 154 204 { "--type", 'T', RTGETOPT_REQ_UINT32 }, // deprecated 155 205 { "-type", 'T', RTGETOPT_REQ_UINT32 }, // deprecated 156 #if 0 /* Changing the controller is fully valid, but the current design on how157 the params are evaluated here doesn't allow two parameter for one158 unit. The target disk path is more important. I leave it for future159 improvments. */160 206 { "--controller", 'C', RTGETOPT_REQ_STRING }, 161 #endif 207 { "--port", 'E', RTGETOPT_REQ_STRING }, 162 208 { "--disk", 'D', RTGETOPT_REQ_STRING }, 163 209 { "--options", 'O', RTGETOPT_REQ_STRING }, … … 343 389 GetState.pDef->pszLong); 344 390 mapArgsMapsPerVsys[ulCurVsys][Utf8StrFmt("controller%u", ulCurUnit)] = ValueUnion.psz; 391 break; 392 393 case 'E': // --port 394 if (enmApplType != LOCAL) 395 return errorSyntax(USAGE_IMPORTAPPLIANCE, 396 Appliance::tr("Option \"%s\" requires preceding --vsys option."), 397 GetState.pDef->pszLong); 398 if (ulCurUnit == (uint32_t)-1) 399 return errorSyntax(USAGE_IMPORTAPPLIANCE, 400 Appliance::tr("Option \"%s\" requires preceding --unit option."), 401 GetState.pDef->pszLong); 402 mapArgsMapsPerVsys[ulCurVsys][Utf8StrFmt("port%u", ulCurUnit)] = ValueUnion.psz; 345 403 break; 346 404 … … 845 903 { 846 904 Utf8StrFmt strTypeArg("disk%u", a); 905 bool fDiskChanged = false; 906 int vrc; 847 907 RTCList<ImportOptions_T> optionsList = options.toList(); 848 849 bstrFinalValue = aVBoxValues[a];850 908 851 909 if (findArgValue(strOverride, pmapArgs, strTypeArg)) 852 910 { 853 if (!optionsList.contains(ImportOptions_ImportToVDI)) 911 if (optionsList.contains(ImportOptions_ImportToVDI)) 912 return errorSyntax(USAGE_IMPORTAPPLIANCE, 913 Appliance::tr("Option --ImportToVDI can not be used together with " 914 "a manually set target path.")); 915 RTUUID uuid; 916 /* Check if this is a uuid. If so, don't touch. */ 917 vrc = RTUuidFromStr(&uuid, strOverride.c_str()); 918 if (vrc != VINF_SUCCESS) 854 919 { 855 RTUUID uuid; 856 /* Check if this is a uuid. If so, don't touch. */ 857 int vrc = RTUuidFromStr(&uuid, strOverride.c_str()); 858 if (vrc != VINF_SUCCESS) 920 /* Make the path absolute. */ 921 if (!RTPathStartsWithRoot(strOverride.c_str())) 859 922 { 860 /* Make the path absolute. */ 861 if (!RTPathStartsWithRoot(strOverride.c_str())) 862 { 863 char pszPwd[RTPATH_MAX]; 864 vrc = RTPathGetCurrent(pszPwd, RTPATH_MAX); 865 if (RT_SUCCESS(vrc)) 866 strOverride = Utf8Str(pszPwd).append(RTPATH_SLASH).append(strOverride); 867 } 923 char pszPwd[RTPATH_MAX]; 924 vrc = RTPathGetCurrent(pszPwd, RTPATH_MAX); 925 if (RT_SUCCESS(vrc)) 926 strOverride = Utf8Str(pszPwd).append(RTPATH_SLASH).append(strOverride); 868 927 } 869 bstrFinalValue = strOverride;870 928 } 871 else 872 { 873 //print some error about incompatible command-line arguments 874 return errorSyntax(USAGE_IMPORTAPPLIANCE, 875 Appliance::tr("Option --ImportToVDI shall not be used together with " 876 "manually set target path.")); 877 878 } 879 880 RTPrintf(Appliance::tr("%2u: Hard disk image: source image=%ls, target path=%ls, %ls\n"), 881 a, 882 aOvfValues[a], 883 bstrFinalValue.raw(), 884 aExtraConfigValues[a]); 929 bstrFinalValue = strOverride; 930 fDiskChanged = true; 885 931 } 886 #if 0 /* Changing the controller is fully valid, but the current design on how 887 the params are evaluated here doesn't allow two parameter for one 888 unit. The target disk path is more important I leave it for future 889 improvments. */ 890 Utf8StrFmt strTypeArg("controller%u", a); 932 933 strTypeArg.printf("controller%u", a); 934 bool fControllerChanged = false; 935 uint32_t uTargetController = (uint32_t)-1; 936 VirtualSystemDescriptionType_T vsdControllerType = VirtualSystemDescriptionType_Ignore; 937 Utf8Str strExtraConfigValue; 891 938 if (findArgValue(strOverride, pmapArgs, strTypeArg)) 892 939 { 893 // strOverride now has the controller index as a number, but we 894 // need a "controller=X" format string 895 strOverride = Utf8StrFmt("controller=%s", strOverride.c_str()); 940 vrc = getStorageControllerDetailsFromStr(strOverride, NULL, &uTargetController); 941 if (RT_FAILURE(vrc)) 942 return errorSyntax(USAGE_IMPORTAPPLIANCE, 943 Appliance::tr("Invalid controller value: '%s'"), 944 strOverride.c_str()); 945 946 vsdControllerType = retTypes[uTargetController]; 947 if (!isStorageControllerType(vsdControllerType)) 948 return errorSyntax(USAGE_IMPORTAPPLIANCE, 949 Appliance::tr("Invalid storage controller specified: %u"), 950 uTargetController); 951 952 fControllerChanged = true; 953 } 954 955 strTypeArg.printf("port%u", a); 956 bool fControllerPortChanged = false; 957 uint32_t uTargetControllerPort = (uint32_t)-1;; 958 if (findArgValue(strOverride, pmapArgs, strTypeArg)) 959 { 960 vrc = getStorageControllerDetailsFromStr(strOverride, NULL, &uTargetControllerPort); 961 if (RT_FAILURE(vrc)) 962 return errorSyntax(USAGE_IMPORTAPPLIANCE, 963 Appliance::tr("Invalid port value: '%s'"), 964 strOverride.c_str()); 965 966 fControllerPortChanged = true; 967 } 968 969 /* 970 * aExtraConfigValues[a] has a format of 'controller=12;channel=0' and is set by 971 * Appliance::interpret() so any parsing errors here aren't due to user-supplied 972 * values so different error messages here. 973 */ 974 uint32_t uOrigController; 975 Utf8Str strOrigController(Bstr(aExtraConfigValues[a]).raw()); 976 vrc = getStorageControllerDetailsFromStr(strOrigController, "controller=", &uOrigController); 977 if (RT_FAILURE(vrc)) 978 return RTMsgErrorExitFailure(Appliance::tr("Failed to extract controller value from ExtraConfig: '%s'"), 979 strOrigController.c_str()); 980 981 uint32_t uOrigControllerPort; 982 vrc = getStorageControllerDetailsFromStr(strOrigController, "channel=", &uOrigControllerPort); 983 if (RT_FAILURE(vrc)) 984 return RTMsgErrorExitFailure(Appliance::tr("Failed to extract channel value from ExtraConfig: '%s'"), 985 strOrigController.c_str()); 986 987 /* 988 * The 'strExtraConfigValue' string is used to display the storage controller and 989 * port details for each virtual hard disk using the more accurate 'controller=' and 990 * 'port=' labels. The aExtraConfigValues[a] string has a format of 991 * 'controller=%u;channel=%u' from Appliance::interpret() which is required as per 992 * the API but for consistency and clarity with the CLI options --controller and 993 * --port we instead use strExtraConfigValue in the output below. 994 */ 995 strExtraConfigValue = Utf8StrFmt("controller=%u;port=%u", uOrigController, uOrigControllerPort); 996 997 if (fControllerChanged || fControllerPortChanged) 998 { 999 /* 1000 * Verify that the new combination of controller and controller port is valid. 1001 * cf. StorageController::i_checkPortAndDeviceValid() 1002 */ 1003 if (uTargetControllerPort == (uint32_t)-1) 1004 uTargetControllerPort = uOrigControllerPort; 1005 if (uTargetController == (uint32_t)-1) 1006 uTargetController = uOrigController; 1007 1008 if ( uOrigController == uTargetController 1009 && uOrigControllerPort == uTargetControllerPort) 1010 return errorSyntax(USAGE_IMPORTAPPLIANCE, 1011 Appliance::tr("Device already attached to controller %u at this port (%u) " 1012 "location."), 1013 uTargetController, 1014 uTargetControllerPort); 1015 1016 if (vsdControllerType == VirtualSystemDescriptionType_Ignore) 1017 vsdControllerType = retTypes[uOrigController]; 1018 if (!isStorageControllerType(vsdControllerType)) 1019 return errorSyntax(USAGE_IMPORTAPPLIANCE, 1020 Appliance::tr("Invalid storage controller specified: %u"), 1021 uOrigController); 1022 1023 ComPtr<IVirtualBox> pVirtualBox = arg->virtualBox; 1024 ComPtr<ISystemProperties> systemProperties; 1025 CHECK_ERROR(pVirtualBox, COMGETTER(SystemProperties)(systemProperties.asOutParam())); 1026 ULONG maxPorts = 0; 1027 StorageBus_T enmStorageBus = StorageBus_Null;; 1028 switch (vsdControllerType) 1029 { 1030 case VirtualSystemDescriptionType_HardDiskControllerIDE: 1031 enmStorageBus = StorageBus_IDE; 1032 break; 1033 case VirtualSystemDescriptionType_HardDiskControllerSATA: 1034 enmStorageBus = StorageBus_SATA; 1035 break; 1036 case VirtualSystemDescriptionType_HardDiskControllerSCSI: 1037 enmStorageBus = StorageBus_SCSI; 1038 break; 1039 case VirtualSystemDescriptionType_HardDiskControllerSAS: 1040 enmStorageBus = StorageBus_SAS; 1041 break; 1042 case VirtualSystemDescriptionType_HardDiskControllerVirtioSCSI: 1043 enmStorageBus = StorageBus_VirtioSCSI; 1044 break; 1045 default: // Not reached since vsdControllerType validated above but silence gcc. 1046 break; 1047 } 1048 CHECK_ERROR_RET(systemProperties, GetMaxPortCountForStorageBus(enmStorageBus, &maxPorts), 1049 RTEXITCODE_FAILURE); 1050 if (uTargetControllerPort >= maxPorts) 1051 return errorSyntax(USAGE_IMPORTAPPLIANCE, 1052 Appliance::tr("Illegal port value: %u. For %ls controllers the only valid values " 1053 "are 0 to %lu (inclusive)"), 1054 uTargetControllerPort, 1055 aVBoxValues[uTargetController], 1056 maxPorts); 1057 1058 /* 1059 * The 'strOverride' string will be mapped to the strExtraConfigCurrent value in 1060 * VirtualSystemDescription::setFinalValues() which is then used in the appliance 1061 * import routines i_importVBoxMachine()/i_importMachineGeneric() later. This 1062 * aExtraConfigValues[] array entry must have a format of 1063 * 'controller=<index>;channel=<c>' as per the API documentation. 1064 */ 1065 strExtraConfigValue = Utf8StrFmt("controller=%u;port=%u", uTargetController, 1066 uTargetControllerPort); 1067 strOverride = Utf8StrFmt("controller=%u;channel=%u", uTargetController, 1068 uTargetControllerPort); 896 1069 Bstr bstrExtraConfigValue = strOverride; 897 1070 bstrExtraConfigValue.detachTo(&aExtraConfigValues[a]); 898 RTPrintf(Appliance::tr("%2u: Hard disk image: source image=%ls, target path=%ls, %ls\n"),899 a,900 aOvfValues[a],901 aVBoxValues[a],902 aExtraConfigValues[a]);903 1071 } 904 #endif 1072 1073 if (fDiskChanged && !fControllerChanged && !fControllerPortChanged) 1074 { 1075 RTPrintf(Appliance::tr("%2u: " 1076 "Hard disk image specified with --disk: source image=%ls, target path=%ls, %s" 1077 "\n (change controller with \"--vsys %u --unit %u --controller <index>\";" 1078 "\n change controller port with \"--vsys %u --unit %u --port <n>\")\n"), 1079 a, 1080 aOvfValues[a], 1081 bstrFinalValue.raw(), 1082 strExtraConfigValue.c_str(), 1083 i, a, 1084 i, a); 1085 } 1086 else if (fDiskChanged && fControllerChanged && !fControllerPortChanged) 1087 { 1088 RTPrintf(Appliance::tr("%2u: " 1089 "Hard disk image specified with --disk and --controller: source image=%ls, target path=%ls, %s" 1090 "\n (change controller port with \"--vsys %u --unit %u --port <n>\")\n"), 1091 a, 1092 aOvfValues[a], 1093 bstrFinalValue.raw(), 1094 strExtraConfigValue.c_str(), 1095 i, a); 1096 } 1097 else if (fDiskChanged && !fControllerChanged && fControllerPortChanged) 1098 { 1099 RTPrintf(Appliance::tr("%2u: " 1100 "Hard disk image specified with --disk and --port: source image=%ls, target path=%ls, %s" 1101 "\n (change controller with \"--vsys %u --unit %u --controller <index>\")\n"), 1102 a, 1103 aOvfValues[a], 1104 bstrFinalValue.raw(), 1105 strExtraConfigValue.c_str(), 1106 i, a); 1107 } 1108 else if (!fDiskChanged && fControllerChanged && fControllerPortChanged) 1109 { 1110 RTPrintf(Appliance::tr("%2u: " 1111 "Hard disk image specified with --controller and --port: source image=%ls, target path=%ls, %s" 1112 "\n (change target path with \"--vsys %u --unit %u --disk path\")\n"), 1113 a, 1114 aOvfValues[a], 1115 bstrFinalValue.raw(), 1116 strExtraConfigValue.c_str(), 1117 i, a); 1118 } 1119 else if (!fDiskChanged && !fControllerChanged && fControllerPortChanged) 1120 { 1121 RTPrintf(Appliance::tr("%2u: " 1122 "Hard disk image specified with --port: source image=%ls, target path=%ls, %s" 1123 "\n (change target path with \"--vsys %u --unit %u --disk path\";" 1124 "\n change controller with \"--vsys %u --unit %u --controller <index>\")\n"), 1125 a, 1126 aOvfValues[a], 1127 bstrFinalValue.raw(), 1128 strExtraConfigValue.c_str(), 1129 i, a, 1130 i, a); 1131 } 1132 else if (!fDiskChanged && fControllerChanged && !fControllerPortChanged) 1133 { 1134 RTPrintf(Appliance::tr("%2u: " 1135 "Hard disk image specified with --controller: source image=%ls, target path=%ls, %s" 1136 "\n (change target path with \"--vsys %u --unit %u --disk path\";" 1137 "\n change controller port with \"--vsys %u --unit %u --port <n>\")\n"), 1138 a, 1139 aOvfValues[a], 1140 bstrFinalValue.raw(), 1141 strExtraConfigValue.c_str(), 1142 i, a, 1143 i, a); 1144 } 1145 else if (fDiskChanged && fControllerChanged && fControllerPortChanged) 1146 { 1147 RTPrintf(Appliance::tr("%2u: " 1148 "Hard disk image specified with --disk and --controller and --port: " 1149 "source image=%ls, target path=%ls, %s\n"), 1150 a, 1151 aOvfValues[a], 1152 bstrFinalValue.raw(), 1153 strExtraConfigValue.c_str()); 1154 } 905 1155 else 906 1156 { … … 913 1163 * and creating one new function which returns 914 1164 * struct ovf::DiskImage for currently processed disk. 915 */1165 */ 916 1166 917 1167 /* … … 982 1232 bstrFinalValue = strOverride; 983 1233 984 RTPrintf(Appliance::tr( 985 "%2u: Hard disk image: source image=%ls, target path=%ls, %ls" 986 "\n (change target path with \"--vsys %u --unit %u --disk path\";" 987 "\n disable with \"--vsys %u --unit %u --ignore\")\n"), 988 a, 989 aOvfValues[a], 990 bstrFinalValue.raw(), 991 aExtraConfigValues[a], 992 i, a, i, a); 1234 RTPrintf(Appliance::tr("%2u: Hard disk image: source image=%ls, target path=%ls, %s" 1235 "\n (change target path with \"--vsys %u --unit %u --disk path\";" 1236 "\n change controller with \"--vsys %u --unit %u --controller <index>\";" 1237 "\n change controller port with \"--vsys %u --unit %u --port <n>\";" 1238 "\n disable with \"--vsys %u --unit %u --ignore\")\n"), 1239 a, aOvfValues[a], bstrFinalValue.raw(), strExtraConfigValue.c_str(), 1240 i, a, 1241 i, a, 1242 i, a, 1243 i, a); 993 1244 } 994 1245 } -
trunk/src/VBox/Main/include/ApplianceImpl.h
r93115 r93480 220 220 ImportStack &stack); 221 221 void i_importMachines(ImportStack &stack); 222 HRESULT i_verifyStorageControllerPortValid(const StorageControllerType_T aStorageControllerType, 223 const uint32_t aControllerPort, 224 ULONG *ulMaxPorts); 222 225 223 226 HRESULT i_preCheckImageAvailability(ImportStack &stack); … … 310 313 std::list<VirtualSystemDescriptionEntry*> i_findByType(VirtualSystemDescriptionType_T aType); 311 314 const VirtualSystemDescriptionEntry* i_findControllerFromID(const Utf8Str &id); 315 const VirtualSystemDescriptionEntry* i_findByIndex(const uint32_t aIndex); 312 316 313 317 void i_importVBoxMachineXML(const xml::ElementNode &elmMachine); -
trunk/src/VBox/Main/include/Global.h
r93410 r93480 168 168 static const char *stringifySessionState(SessionState_T aState); 169 169 170 /** 171 * Stringify a device type. 172 * 173 * Drop the Global:: prefix and include StringifyEnums.h for an untranslated 174 * version of this method. 175 * 176 * @returns Pointer to a read only string. 177 * @param aType The device type. 178 */ 179 static const char *stringifyDeviceType(DeviceType_T aType); 180 181 /** 182 * Stringify a storage controller type. 183 * 184 * Drop the Global:: prefix and include StringifyEnums.h for an untranslated 185 * version of this method. 186 * 187 * @returns Pointer to a read only string. 188 * @param aType The storage controller type. 189 */ 190 static const char *stringifyStorageControllerType(StorageControllerType_T aType); 191 170 192 #if 0 /* unused */ 171 193 /** … … 179 201 */ 180 202 static const char *stringifyStorageBus(StorageBus_T aBus); 181 182 /**183 * Stringify a device type.184 *185 * Drop the Global:: prefix and include StringifyEnums.h for an untranslated186 * version of this method.187 *188 * @returns Pointer to a read only string.189 * @param aType The device type.190 */191 static const char *stringifyDeviceType(DeviceType_T aType);192 203 193 204 /** -
trunk/src/VBox/Main/src-all/Global.cpp
r93410 r93480 635 635 } 636 636 637 /*static*/ const char * 638 Global::stringifyStorageControllerType(StorageControllerType_T aType) 639 { 640 switch (aType) 641 { 642 case StorageControllerType_Null: return GlobalCtx::tr("Null"); 643 case StorageControllerType_LsiLogic: return GlobalCtx::tr("LsiLogic"); 644 case StorageControllerType_BusLogic: return GlobalCtx::tr("BusLogic"); 645 case StorageControllerType_IntelAhci: return GlobalCtx::tr("AHCI"); 646 case StorageControllerType_PIIX3: return GlobalCtx::tr("PIIX3"); 647 case StorageControllerType_PIIX4 : return GlobalCtx::tr("PIIX4"); 648 case StorageControllerType_ICH6: return GlobalCtx::tr("ICH6"); 649 case StorageControllerType_I82078: return GlobalCtx::tr("I82078"); 650 case StorageControllerType_LsiLogicSas: return GlobalCtx::tr("LsiLogicSas"); 651 case StorageControllerType_USB: return GlobalCtx::tr("USB"); 652 case StorageControllerType_NVMe: return GlobalCtx::tr("NVMe"); 653 case StorageControllerType_VirtioSCSI: return GlobalCtx::tr("VirtioSCSI"); 654 default: 655 AssertMsgFailedReturn(("%d (%#x)\n", aType, aType), ::stringifyStorageControllerType(aType)); 656 } 657 } 658 659 /*static*/ const char * 660 Global::stringifyDeviceType(DeviceType_T aType) 661 { 662 switch (aType) 663 { 664 case DeviceType_Null: return GlobalCtx::tr("Null"); 665 case DeviceType_Floppy: return GlobalCtx::tr("Floppy"); 666 case DeviceType_DVD: return GlobalCtx::tr("DVD"); 667 case DeviceType_HardDisk: return GlobalCtx::tr("HardDisk"); 668 case DeviceType_Network: return GlobalCtx::tr("Network"); 669 case DeviceType_USB: return GlobalCtx::tr("USB"); 670 case DeviceType_SharedFolder: return GlobalCtx::tr("ShardFolder"); 671 default: 672 AssertMsgFailedReturn(("%d (%#x)\n", aType, aType), ::stringifyDeviceType(aType)); 673 } 674 } 675 637 676 #if 0 /* unused */ 638 677 … … 656 695 657 696 /*static*/ const char * 658 Global::stringifyDeviceType(DeviceType_T aType)659 {660 switch (aType)661 {662 case DeviceType_Null: return GlobalCtx::tr("Null");663 case DeviceType_Floppy: return GlobalCtx::tr("Floppy");664 case DeviceType_DVD: return GlobalCtx::tr("DVD");665 case DeviceType_HardDisk: return GlobalCtx::tr("HardDisk");666 case DeviceType_Network: return GlobalCtx::tr("Network");667 case DeviceType_USB: return GlobalCtx::tr("USB");668 case DeviceType_SharedFolder: return GlobalCtx::tr("ShardFolder");669 default:670 AssertMsgFailedReturn(("%d (%#x)\n", aType, aType), ::stringifyDeviceType(aType));671 }672 }673 674 /*static*/ const char *675 697 Global::stringifyReason(Reason_T aReason) 676 698 { -
trunk/src/VBox/Main/src-server/ApplianceImpl.cpp
r93115 r93480 1828 1828 } 1829 1829 1830 /** 1831 * Private method; walks through the array of VirtualSystemDescriptionEntry entries 1832 * and returns the one matching the given index. 1833 */ 1834 const VirtualSystemDescriptionEntry* VirtualSystemDescription::i_findByIndex(const uint32_t aIndex) 1835 { 1836 vector<VirtualSystemDescriptionEntry>::const_iterator it; 1837 for (it = m->maDescriptions.begin(); 1838 it != m->maDescriptions.end(); 1839 ++it) 1840 { 1841 const VirtualSystemDescriptionEntry &d = *it; 1842 if (d.ulIndex == aIndex) 1843 return &d; 1844 } 1845 1846 return NULL; 1847 } 1848 -
trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
r93115 r93480 4305 4305 4306 4306 /** 4307 * Helper routine to parse the ExtraData Utf8Str for a storage controller's 4308 * value or channel value. 4309 * 4310 * @param aExtraData The ExtraData string with a format of 4311 * 'controller=13;channel=3'. 4312 * @param pszKey The string being looked up, either 'controller' or 4313 * 'channel'. 4314 * @param puVal The integer value of the 'controller=' or 'channel=' 4315 * key in the ExtraData string. 4316 * @returns COM status code. 4317 * @throws Nothing. 4318 */ 4319 static int getStorageControllerDetailsFromStr(const com::Utf8Str &aExtraData, const char *pszKey, uint32_t *puVal) 4320 { 4321 size_t posKey = aExtraData.find(pszKey); 4322 if (posKey == Utf8Str::npos) 4323 return VERR_INVALID_PARAMETER; 4324 4325 int vrc = RTStrToUInt32Ex(aExtraData.c_str() + posKey + strlen(pszKey), NULL, 0, puVal); 4326 if (vrc == VWRN_NUMBER_TOO_BIG || vrc == VWRN_NEGATIVE_UNSIGNED) 4327 return VERR_INVALID_PARAMETER; 4328 4329 return vrc; 4330 } 4331 4332 /** 4333 * Verifies the validity of a storage controller's channel (aka controller port). 4334 * 4335 * @param aStorageControllerType The type of storage controller as idenfitied 4336 * by the enum of type StorageControllerType_T. 4337 * @param uControllerPort The controller port value. 4338 * @param aMaxPortCount The maximum number of ports allowed for this 4339 * storage controller type. 4340 * @returns COM status code. 4341 * @throws Nothing. 4342 */ 4343 HRESULT Appliance::i_verifyStorageControllerPortValid(const StorageControllerType_T aStorageControllerType, 4344 const uint32_t uControllerPort, 4345 ULONG *aMaxPortCount) 4346 { 4347 SystemProperties *pSysProps; 4348 pSysProps = mVirtualBox->i_getSystemProperties(); 4349 if (pSysProps == NULL) 4350 return VBOX_E_OBJECT_NOT_FOUND; 4351 4352 StorageBus_T enmStorageBus = StorageBus_Null; 4353 HRESULT vrc = pSysProps->GetStorageBusForStorageControllerType(aStorageControllerType, &enmStorageBus); 4354 if (FAILED(vrc)) 4355 return vrc; 4356 4357 vrc = pSysProps->GetMaxPortCountForStorageBus(enmStorageBus, aMaxPortCount); 4358 if (FAILED(vrc)) 4359 return vrc; 4360 4361 if (uControllerPort >= *aMaxPortCount) 4362 return E_INVALIDARG; 4363 4364 return S_OK; 4365 } 4366 4367 /** 4307 4368 * Imports one OVF virtual system (described by the given ovf::VirtualSystem and VirtualSystemDescription) 4308 4369 * into VirtualBox by creating an IMachine instance, which is returned. … … 5014 5075 throw rc; 5015 5076 5016 // find the hard disk controller to which we should attach5017 ovf::HardDiskController hdc = (*vsysThis.mapControllers.find(ovfVdisk.strIdController)).second;5018 5019 5077 // this is for rollback later 5020 5078 MyHardDiskAttachment mhda; 5021 5079 mhda.pMachine = pNewMachine; 5080 5081 // find the hard disk controller to which we should attach 5082 ovf::HardDiskController hdc; 5083 5084 /* 5085 * Before importing the virtual hard disk found above (diCurrent/vsdeTargetHD) first 5086 * check if the user requested to change either the controller it is to be attached 5087 * to and/or the controller port (aka 'channel') on the controller. 5088 */ 5089 if ( !vsdeTargetHD->strExtraConfigCurrent.isEmpty() 5090 && vsdeTargetHD->strExtraConfigSuggested != vsdeTargetHD->strExtraConfigCurrent) 5091 { 5092 int vrc; 5093 uint32_t uTargetControllerIndex; 5094 vrc = getStorageControllerDetailsFromStr(vsdeTargetHD->strExtraConfigCurrent, "controller=", 5095 &uTargetControllerIndex); 5096 if (RT_FAILURE(vrc)) 5097 throw setError(E_FAIL, 5098 tr("Target controller value invalid or missing: '%s'"), 5099 vsdeTargetHD->strExtraConfigCurrent.c_str()); 5100 5101 uint32_t uNewControllerPortValue; 5102 vrc = getStorageControllerDetailsFromStr(vsdeTargetHD->strExtraConfigCurrent, "channel=", 5103 &uNewControllerPortValue); 5104 if (RT_FAILURE(vrc)) 5105 throw setError(E_FAIL, 5106 tr("Target controller port ('channel=') invalid or missing: '%s'"), 5107 vsdeTargetHD->strExtraConfigCurrent.c_str()); 5108 5109 const VirtualSystemDescriptionEntry *vsdeTargetController; 5110 vsdeTargetController = vsdescThis->i_findByIndex(uTargetControllerIndex); 5111 if (!vsdeTargetController) 5112 throw setError(E_FAIL, 5113 tr("Failed to find storage controller '%u' in the System Description list"), 5114 uTargetControllerIndex); 5115 5116 hdc = (*vsysThis.mapControllers.find(vsdeTargetController->strRef.c_str())).second; 5117 5118 StorageControllerType_T hdStorageControllerType = StorageControllerType_Null; 5119 switch (hdc.system) 5120 { 5121 case ovf::HardDiskController::IDE: 5122 hdStorageControllerType = StorageControllerType_PIIX3; 5123 break; 5124 case ovf::HardDiskController::SATA: 5125 hdStorageControllerType = StorageControllerType_IntelAhci; 5126 break; 5127 case ovf::HardDiskController::SCSI: 5128 { 5129 if (hdc.strControllerType.compare("lsilogicsas")==0) 5130 hdStorageControllerType = StorageControllerType_LsiLogicSas; 5131 else 5132 hdStorageControllerType = StorageControllerType_LsiLogic; 5133 break; 5134 } 5135 case ovf::HardDiskController::VIRTIOSCSI: 5136 hdStorageControllerType = StorageControllerType_VirtioSCSI; 5137 break; 5138 default: 5139 throw setError(E_FAIL, 5140 tr("Invalid hard disk contoller type: '%d'"), 5141 hdc.system); 5142 break; 5143 } 5144 5145 ULONG ulMaxPorts; 5146 rc = i_verifyStorageControllerPortValid(hdStorageControllerType, 5147 uNewControllerPortValue, 5148 &ulMaxPorts); 5149 if (FAILED(rc)) 5150 { 5151 if (rc == E_INVALIDARG) 5152 { 5153 const char *pcszSCType = Global::stringifyStorageControllerType(hdStorageControllerType); 5154 throw setError(E_INVALIDARG, 5155 tr("Illegal channel: '%u'. For %s controllers the valid values are " 5156 "0 to %lu (inclusive).\n"), uNewControllerPortValue, pcszSCType, ulMaxPorts-1); 5157 } 5158 else 5159 throw rc; 5160 } 5161 5162 unconst(ovfVdisk.ulAddressOnParent) = uNewControllerPortValue; 5163 } 5164 else 5165 hdc = (*vsysThis.mapControllers.find(ovfVdisk.strIdController)).second; 5166 5022 5167 5023 5168 i_convertDiskAttachmentValues(hdc, … … 5262 5407 * failures. A long fixed bug, however the OVF files are long lived. */ 5263 5408 settings::StorageControllersList &llControllers = config.hardwareMachine.storage.llStorageControllers; 5264 Guid hdUuid;5265 5409 uint32_t cDisks = 0; 5266 5410 bool fInconsistent = false; … … 5271 5415 ++it3) 5272 5416 { 5417 Guid hdUuid; 5273 5418 settings::AttachedDevicesList &llAttachments = it3->llAttachedDevices; 5274 5419 settings::AttachedDevicesList::iterator it4 = llAttachments.begin(); … … 5364 5509 continue; 5365 5510 } 5366 5367 5368 5369 5370 5371 5372 5373 5374 5511 5375 5512 /* … … 5444 5581 tr("Internal inconsistency looking up disk image '%s'"), 5445 5582 diCurrent.strHref.c_str()); 5446 5447 5448 5449 5450 5451 5583 } 5452 5584 else … … 5473 5605 bool fFound = false; 5474 5606 Utf8Str strUuid; 5607 5608 /* 5609 * Before importing the virtual hard disk found above (diCurrent/vsdeTargetHD) first 5610 * check if the user requested to change either the controller it is to be attached 5611 * to and/or the controller port (aka 'channel') on the controller. 5612 */ 5613 if ( !vsdeTargetHD->strExtraConfigCurrent.isEmpty() 5614 && vsdeTargetHD->strExtraConfigSuggested != vsdeTargetHD->strExtraConfigCurrent) 5615 { 5616 /* 5617 * First, we examine the extra configuration values for this vdisk: 5618 * vsdeTargetHD->strExtraConfigSuggested 5619 * vsdeTargetHD->strExtraConfigCurrent 5620 * in order to extract both the "before" and "after" storage controller and port 5621 * details. The strExtraConfigSuggested string contains the current controller 5622 * and port the vdisk is attached to and is populated by Appliance::interpret() 5623 * when processing the OVF data; it is in the following format: 5624 * 'controller=12;channel=0' (the 'channel=' label for the controller port is 5625 * historical and is documented as such in the SDK so can't be changed). The 5626 * strExtraConfigSuggested string contains the target controller and port specified 5627 * by the user and it has the same format. The 'controller=' value is not a 5628 * controller-ID but rather it is the index for the corresponding storage controller 5629 * in the array of VirtualSystemDescriptionEntry entries. 5630 */ 5631 int vrc; 5632 uint32_t uOrigControllerIndex; 5633 vrc = getStorageControllerDetailsFromStr(vsdeTargetHD->strExtraConfigSuggested, "controller=", &uOrigControllerIndex); 5634 if (RT_FAILURE(vrc)) 5635 throw setError(E_FAIL, 5636 tr("Original controller value invalid or missing: '%s'"), 5637 vsdeTargetHD->strExtraConfigSuggested.c_str()); 5638 5639 uint32_t uTargetControllerIndex; 5640 vrc = getStorageControllerDetailsFromStr(vsdeTargetHD->strExtraConfigCurrent, "controller=", &uTargetControllerIndex); 5641 if (RT_FAILURE(vrc)) 5642 throw setError(E_FAIL, 5643 tr("Target controller value invalid or missing: '%s'"), 5644 vsdeTargetHD->strExtraConfigCurrent.c_str()); 5645 5646 uint32_t uOrigControllerPortValue; 5647 vrc = getStorageControllerDetailsFromStr(vsdeTargetHD->strExtraConfigSuggested, "channel=", 5648 &uOrigControllerPortValue); 5649 if (RT_FAILURE(vrc)) 5650 throw setError(E_FAIL, 5651 tr("Original controller port ('channel=') invalid or missing: '%s'"), 5652 vsdeTargetHD->strExtraConfigSuggested.c_str()); 5653 5654 uint32_t uNewControllerPortValue; 5655 vrc = getStorageControllerDetailsFromStr(vsdeTargetHD->strExtraConfigCurrent, "channel=", &uNewControllerPortValue); 5656 if (RT_FAILURE(vrc)) 5657 throw setError(E_FAIL, 5658 tr("Target controller port ('channel=') invalid or missing: '%s'"), 5659 vsdeTargetHD->strExtraConfigCurrent.c_str()); 5660 5661 /* 5662 * Second, now that we have the storage controller indexes we locate the corresponding 5663 * VirtualSystemDescriptionEntry (VSDE) for both storage controllers which contain 5664 * identifying details which will be needed later when walking the list of storage 5665 * controllers. 5666 */ 5667 const VirtualSystemDescriptionEntry *vsdeOrigController; 5668 vsdeOrigController = vsdescThis->i_findByIndex(uOrigControllerIndex); 5669 if (!vsdeOrigController) 5670 throw setError(E_FAIL, 5671 tr("Failed to find storage controller '%u' in the System Description list"), 5672 uOrigControllerIndex); 5673 5674 const VirtualSystemDescriptionEntry *vsdeTargetController; 5675 vsdeTargetController = vsdescThis->i_findByIndex(uTargetControllerIndex); 5676 if (!vsdeTargetController) 5677 throw setError(E_FAIL, 5678 tr("Failed to find storage controller '%u' in the System Description list"), 5679 uTargetControllerIndex); 5680 5681 /* 5682 * Third, grab the UUID of the current vdisk so we can identify which device 5683 * attached to the original storage controller needs to be updated (channel) and/or 5684 * removed. 5685 */ 5686 ovf::DiskImagesMap::const_iterator itDiskImageMap = stack.mapDisks.find(vsdeTargetHD->strRef); 5687 if (itDiskImageMap == stack.mapDisks.end()) 5688 throw setError(E_FAIL, 5689 tr("Failed to find virtual disk '%s' in DiskImagesMap"), 5690 vsdeTargetHD->strVBoxCurrent.c_str()); 5691 const ovf::DiskImage &targetDiskImage = itDiskImageMap->second; 5692 Utf8Str strTargetDiskUuid = targetDiskImage.uuidVBox;; 5693 5694 /* 5695 * Fourth, walk the attached devices of the original storage controller to find the 5696 * current vdisk and update the controller port (aka channel) value if necessary and 5697 * also remove the vdisk from this controller if needed. 5698 * 5699 * A short note on the choice of which items to compare when determining the type of 5700 * storage controller here and below in the vdisk addition scenario: 5701 * + The VirtualSystemDescriptionEntry 'strOvf' field is populated from the OVF 5702 * data which can contain a value like 'vmware.sata.ahci' if created by VMWare so 5703 * it isn't a reliable choice. 5704 * + The settings::StorageController 'strName' field can have varying content based 5705 * on the version of the settings file, e.g. 'IDE Controller' vs. 'IDE' so it 5706 * isn't a reliable choice. Further, this field can contain 'SATA' whereas 5707 * 'AHCI' is used in 'strOvf' and 'strVBoxSuggested'. 5708 * + The VirtualSystemDescriptionEntry 'strVBoxSuggested' field is populated by 5709 * Appliance::interpret()->VirtualSystemDescription::i_addEntry() and is thus 5710 * under VBox's control and has a fixed format and predictable content. 5711 */ 5712 bool fDiskRemoved = false; 5713 settings::AttachedDevice originalAttachedDevice; 5714 settings::StorageControllersList::iterator itSCL; 5715 for (itSCL = config.hardwareMachine.storage.llStorageControllers.begin(); 5716 itSCL != config.hardwareMachine.storage.llStorageControllers.end(); 5717 ++itSCL) 5718 { 5719 settings::StorageController &SC = *itSCL; 5720 const char *pcszSCType = Global::stringifyStorageControllerType(SC.controllerType); 5721 5722 /* There can only be one storage controller of each type in the OVF data. */ 5723 if (!vsdeOrigController->strVBoxSuggested.compare(pcszSCType, Utf8Str::CaseInsensitive)) 5724 { 5725 settings::AttachedDevicesList::iterator itAD; 5726 for (itAD = SC.llAttachedDevices.begin(); 5727 itAD != SC.llAttachedDevices.end(); 5728 ++itAD) 5729 { 5730 settings::AttachedDevice &AD = *itAD; 5731 5732 if (AD.uuid.toString() == strTargetDiskUuid) 5733 { 5734 ULONG ulMaxPorts; 5735 rc = i_verifyStorageControllerPortValid(SC.controllerType, 5736 uNewControllerPortValue, 5737 &ulMaxPorts); 5738 if (FAILED(rc)) 5739 { 5740 if (rc == E_INVALIDARG) 5741 throw setError(E_INVALIDARG, 5742 tr("Illegal channel: '%u'. For %s controllers the valid values are " 5743 "0 to %lu (inclusive).\n"), uNewControllerPortValue, pcszSCType, ulMaxPorts-1); 5744 else 5745 throw rc; 5746 } 5747 5748 if (uOrigControllerPortValue != uNewControllerPortValue) 5749 { 5750 AD.lPort = uNewControllerPortValue; 5751 } 5752 if (uOrigControllerIndex != uTargetControllerIndex) 5753 { 5754 LogFunc(("Removing vdisk '%s' (uuid = %RTuuid) from the %s storage controller.\n", 5755 vsdeTargetHD->strVBoxCurrent.c_str(), 5756 itAD->uuid.raw(), 5757 SC.strName.c_str())); 5758 originalAttachedDevice = AD; 5759 SC.llAttachedDevices.erase(itAD); 5760 fDiskRemoved = true; 5761 } 5762 } 5763 } 5764 } 5765 } 5766 5767 /* 5768 * Fifth, if we are moving the vdisk to a different controller and not just changing 5769 * the channel then we walk the attached devices of the target controller and check 5770 * for conflicts before adding the vdisk detached/removed above. 5771 */ 5772 bool fDiskAdded = false; 5773 if (fDiskRemoved) 5774 { 5775 for (itSCL = config.hardwareMachine.storage.llStorageControllers.begin(); 5776 itSCL != config.hardwareMachine.storage.llStorageControllers.end(); 5777 ++itSCL) 5778 { 5779 settings::StorageController &SC = *itSCL; 5780 const char *pcszSCType = Global::stringifyStorageControllerType(SC.controllerType); 5781 5782 /* There can only be one storage controller of each type in the OVF data. */ 5783 if (!vsdeTargetController->strVBoxSuggested.compare(pcszSCType, Utf8Str::CaseInsensitive)) 5784 { 5785 settings::AttachedDevicesList::iterator itAD; 5786 for (itAD = SC.llAttachedDevices.begin(); 5787 itAD != SC.llAttachedDevices.end(); 5788 ++itAD) 5789 { 5790 settings::AttachedDevice &AD = *itAD; 5791 if ( AD.lDevice == originalAttachedDevice.lDevice 5792 && AD.lPort == originalAttachedDevice.lPort) 5793 throw setError(E_FAIL, 5794 tr("Device of type '%s' already attached to the %s controller at this " 5795 "port/channel (%d)."), 5796 Global::stringifyDeviceType(AD.deviceType), pcszSCType, AD.lPort); 5797 } 5798 5799 LogFunc(("Adding vdisk '%s' (uuid = %RTuuid) to the %s storage controller\n", 5800 vsdeTargetHD->strVBoxCurrent.c_str(), 5801 originalAttachedDevice.uuid.raw(), 5802 SC.strName.c_str())); 5803 SC.llAttachedDevices.push_back(originalAttachedDevice); 5804 fDiskAdded = true; 5805 } 5806 } 5807 5808 if (!fDiskAdded) 5809 throw setError(E_FAIL, 5810 tr("Failed to add disk '%s' (uuid=%RTuuid) to the %s storage controller."), 5811 vsdeTargetHD->strVBoxCurrent.c_str(), 5812 originalAttachedDevice.uuid.raw(), 5813 vsdeTargetController->strVBoxSuggested.c_str()); 5814 } 5815 5816 /* 5817 * Sixth, update the machine settings since we've changed the storage controller 5818 * and/or controller port for this vdisk. 5819 */ 5820 AutoWriteLock vboxLock(mVirtualBox COMMA_LOCKVAL_SRC_POS); 5821 mVirtualBox->i_saveSettings(); 5822 vboxLock.release(); 5823 } 5475 5824 5476 5825 // for each storage controller... … … 5656 6005 VirtualSystemDescriptionEntry *vsdeSF1 = vsdeSettingsFile.front(); 5657 6006 if (vsdeSF1->strVBoxCurrent != vsdeSF1->strVBoxSuggested) 5658 stack.strSettingsFilename = vsdeSF1->strVBoxCurrent;6007 stack.strSettingsFilename = vsdeSF1->strVBoxCurrent; 5659 6008 } 5660 6009 if (stack.strSettingsFilename.isEmpty())
Note:
See TracChangeset
for help on using the changeset viewer.