VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/ApplianceImpl.cpp@ 94460

最後變更 在這個檔案從94460是 94460,由 vboxsync 提交於 3 年 前

VBox/ostypes.h+Main/Global,Machine,UnattendedInstaller+FE/Qt: First pass
at updating the variety of Linux OS subtypes used at install time along
with their corresponding recommended installation defaults based on each
vendor's respective documentation. bugref:5936

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 73.0 KB
 
1/* $Id: ApplianceImpl.cpp 94460 2022-04-04 20:30:21Z vboxsync $ */
2/** @file
3 * IAppliance and IVirtualSystem COM class implementations.
4 */
5
6/*
7 * Copyright (C) 2008-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_MAIN_APPLIANCE
23#include <iprt/path.h>
24#include <iprt/cpp/path.h>
25#include <iprt/cpp/utils.h>
26#include <VBox/com/array.h>
27#include <map>
28
29#include "ApplianceImpl.h"
30#include "VFSExplorerImpl.h"
31#include "VirtualBoxImpl.h"
32#include "GuestOSTypeImpl.h"
33#include "Global.h"
34#include "ProgressImpl.h"
35#include "MachineImpl.h"
36#include "SystemPropertiesImpl.h"
37#include "AutoCaller.h"
38#include "LoggingNew.h"
39#include "CertificateImpl.h"
40
41#include "ApplianceImplPrivate.h"
42
43using namespace std;
44
45
46/*********************************************************************************************************************************
47* Global Variables *
48*********************************************************************************************************************************/
49static const char * const g_pszISOURI = "http://www.ecma-international.org/publications/standards/Ecma-119.htm";
50static const char * const g_pszVMDKStreamURI = "http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized";
51static const char * const g_pszVMDKSparseURI = "http://www.vmware.com/specifications/vmdk.html#sparse";
52static const char * const g_pszVMDKCompressedURI = "http://www.vmware.com/specifications/vmdk.html#compressed";
53static const char * const g_pszVMDKCompressedURI2 = "http://www.vmware.com/interfaces/specifications/vmdk.html#compressed";
54static const char * const g_pszrVHDURI = "http://go.microsoft.com/fwlink/?LinkId=137171";
55static char g_szIsoBackend[128];
56static char g_szVmdkBackend[128];
57static char g_szVhdBackend[128];
58/** Set after the g_szXxxxBackend variables has been initialized. */
59static bool volatile g_fInitializedBackendNames = false;
60
61static struct
62{
63 const char *pszUri, *pszBackend;
64} const g_aUriToBackend[] =
65{
66 { g_pszISOURI, g_szIsoBackend },
67 { g_pszVMDKStreamURI, g_szVmdkBackend },
68 { g_pszVMDKSparseURI, g_szVmdkBackend },
69 { g_pszVMDKCompressedURI, g_szVmdkBackend },
70 { g_pszVMDKCompressedURI2, g_szVmdkBackend },
71 { g_pszrVHDURI, g_szVhdBackend },
72};
73
74static std::map<Utf8Str, Utf8Str> supportedStandardsURI;
75
76static struct
77{
78 ovf::CIMOSType_T cim;
79 VBOXOSTYPE osType;
80} const g_aOsTypes[] =
81{
82 { ovf::CIMOSType_CIMOS_Unknown, VBOXOSTYPE_Unknown },
83 { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2 },
84 { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2Warp3 },
85 { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2Warp4 },
86 { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS2Warp45 },
87 { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_OS21x },
88 { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_ECS },
89 { ovf::CIMOSType_CIMOS_OS2, VBOXOSTYPE_ArcaOS },
90 { ovf::CIMOSType_CIMOS_MSDOS, VBOXOSTYPE_DOS },
91 { ovf::CIMOSType_CIMOS_WIN3x, VBOXOSTYPE_Win31 },
92 { ovf::CIMOSType_CIMOS_WIN95, VBOXOSTYPE_Win95 },
93 { ovf::CIMOSType_CIMOS_WIN98, VBOXOSTYPE_Win98 },
94 { ovf::CIMOSType_CIMOS_WINNT, VBOXOSTYPE_WinNT },
95 { ovf::CIMOSType_CIMOS_WINNT, VBOXOSTYPE_WinNT4 },
96 { ovf::CIMOSType_CIMOS_WINNT, VBOXOSTYPE_WinNT3x },
97 { ovf::CIMOSType_CIMOS_NetWare, VBOXOSTYPE_Netware },
98 { ovf::CIMOSType_CIMOS_NovellOES, VBOXOSTYPE_Netware },
99 { ovf::CIMOSType_CIMOS_Solaris, VBOXOSTYPE_Solaris },
100 { ovf::CIMOSType_CIMOS_SunOS, VBOXOSTYPE_Solaris },
101 { ovf::CIMOSType_CIMOS_FreeBSD, VBOXOSTYPE_FreeBSD },
102 { ovf::CIMOSType_CIMOS_NetBSD, VBOXOSTYPE_NetBSD },
103 { ovf::CIMOSType_CIMOS_QNX, VBOXOSTYPE_QNX },
104 { ovf::CIMOSType_CIMOS_Windows2000, VBOXOSTYPE_Win2k },
105 { ovf::CIMOSType_CIMOS_WindowsMe, VBOXOSTYPE_WinMe },
106 { ovf::CIMOSType_CIMOS_OpenBSD, VBOXOSTYPE_OpenBSD },
107 { ovf::CIMOSType_CIMOS_WindowsXP, VBOXOSTYPE_WinXP },
108 { ovf::CIMOSType_CIMOS_WindowsXPEmbedded, VBOXOSTYPE_WinXP },
109 { ovf::CIMOSType_CIMOS_WindowsEmbeddedforPointofService, VBOXOSTYPE_WinXP },
110 { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2003, VBOXOSTYPE_Win2k3 },
111 { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2003_64, VBOXOSTYPE_Win2k3_x64 },
112 { ovf::CIMOSType_CIMOS_WindowsXP_64, VBOXOSTYPE_WinXP_x64 },
113 { ovf::CIMOSType_CIMOS_WindowsVista, VBOXOSTYPE_WinVista },
114 { ovf::CIMOSType_CIMOS_WindowsVista_64, VBOXOSTYPE_WinVista_x64 },
115 { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2008, VBOXOSTYPE_Win2k8 },
116 { ovf::CIMOSType_CIMOS_MicrosoftWindowsServer2008_64, VBOXOSTYPE_Win2k8_x64 },
117 { ovf::CIMOSType_CIMOS_FreeBSD_64, VBOXOSTYPE_FreeBSD_x64 },
118 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS },
119 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS_x64 }, // there is no CIM 64-bit type for this
120 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS106 },
121 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS106_x64 },
122 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS107_x64 },
123 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS108_x64 },
124 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS109_x64 },
125 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS1010_x64 },
126 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS1011_x64 },
127 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS1012_x64 },
128 { ovf::CIMOSType_CIMOS_MACOS, VBOXOSTYPE_MacOS1013_x64 },
129
130 // Linuxes
131 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux, VBOXOSTYPE_RedHat },
132 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat_x64 },
133 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux, VBOXOSTYPE_RedHat3 },
134 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat3_x64 },
135 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux, VBOXOSTYPE_RedHat4 },
136 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat4_x64 },
137 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux, VBOXOSTYPE_RedHat5 },
138 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat5_x64 },
139 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux, VBOXOSTYPE_RedHat6 },
140 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat6_x64 },
141 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat7_x64 }, // 64-bit only
142 { ovf::CIMOSType_CIMOS_RedHatEnterpriseLinux_64, VBOXOSTYPE_RedHat8_x64 }, // 64-bit only
143 { ovf::CIMOSType_CIMOS_Solaris_64, VBOXOSTYPE_Solaris_x64 },
144 { ovf::CIMOSType_CIMOS_SUSE, VBOXOSTYPE_OpenSUSE },
145 { ovf::CIMOSType_CIMOS_SLES, VBOXOSTYPE_SUSE_LE },
146 { ovf::CIMOSType_CIMOS_NovellLinuxDesktop, VBOXOSTYPE_OpenSUSE },
147 { ovf::CIMOSType_CIMOS_SUSE_64, VBOXOSTYPE_OpenSUSE_x64 },
148 { ovf::CIMOSType_CIMOS_SLES_64, VBOXOSTYPE_SUSE_LE_x64 },
149 { ovf::CIMOSType_CIMOS_SUSE_64, VBOXOSTYPE_OpenSUSE_Leap_x64 }, // 64-bit only
150 { ovf::CIMOSType_CIMOS_SUSE, VBOXOSTYPE_OpenSUSE_Tumbleweed },
151 { ovf::CIMOSType_CIMOS_SUSE_64, VBOXOSTYPE_OpenSUSE_Tumbleweed_x64 },
152 { ovf::CIMOSType_CIMOS_LINUX, VBOXOSTYPE_Linux },
153 { ovf::CIMOSType_CIMOS_LINUX, VBOXOSTYPE_Linux22 },
154 { ovf::CIMOSType_CIMOS_SunJavaDesktopSystem, VBOXOSTYPE_Linux },
155 { ovf::CIMOSType_CIMOS_TurboLinux, VBOXOSTYPE_Turbolinux },
156 { ovf::CIMOSType_CIMOS_TurboLinux_64, VBOXOSTYPE_Turbolinux_x64 },
157 { ovf::CIMOSType_CIMOS_Mandriva, VBOXOSTYPE_Mandriva },
158 { ovf::CIMOSType_CIMOS_Mandriva_64, VBOXOSTYPE_Mandriva_x64 },
159 { ovf::CIMOSType_CIMOS_Mandriva, VBOXOSTYPE_OpenMandriva_Lx },
160 { ovf::CIMOSType_CIMOS_Mandriva_64, VBOXOSTYPE_OpenMandriva_Lx_x64 },
161 { ovf::CIMOSType_CIMOS_Mandriva, VBOXOSTYPE_PCLinuxOS },
162 { ovf::CIMOSType_CIMOS_Mandriva_64, VBOXOSTYPE_PCLinuxOS_x64 },
163 { ovf::CIMOSType_CIMOS_Mandriva, VBOXOSTYPE_Mageia },
164 { ovf::CIMOSType_CIMOS_Mandriva_64, VBOXOSTYPE_Mageia_x64 },
165 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu },
166 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu_x64 },
167 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu10_LTS },
168 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu10_LTS_x64 },
169 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu10 },
170 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu10_x64 },
171 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu11 },
172 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu11_x64 },
173 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu12_LTS },
174 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu12_LTS_x64 },
175 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu12 },
176 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu12_x64 },
177 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu13 },
178 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu13_x64 },
179 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu14_LTS },
180 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu14_LTS_x64 },
181 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu14 },
182 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu14_x64 },
183 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu15 },
184 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu15_x64 },
185 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu16_LTS },
186 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu16_LTS_x64 },
187 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu16 },
188 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu16_x64 },
189 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu17 },
190 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu17_x64 },
191 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu18_LTS },
192 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu18_LTS_x64 },
193 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu18 },
194 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu18_x64 },
195 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Ubuntu19 },
196 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu19_x64 },
197 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu20_LTS_x64 },
198 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu20_x64 },
199 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu21_x64 },
200 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu22_LTS_x64 },
201 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Ubuntu22_x64 },
202 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Lubuntu },
203 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Lubuntu_x64 },
204 { ovf::CIMOSType_CIMOS_Ubuntu, VBOXOSTYPE_Xubuntu },
205 { ovf::CIMOSType_CIMOS_Ubuntu_64, VBOXOSTYPE_Xubuntu_x64 },
206 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian },
207 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian_x64 },
208 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian31 },
209 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian4 },
210 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian4_x64 },
211 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian5 },
212 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian5_x64 },
213 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian6 },
214 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian6_x64 },
215 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian7 },
216 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian7_x64 },
217 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian8 },
218 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian8_x64 },
219 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian9 },
220 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian9_x64 },
221 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian10 },
222 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian10_x64 },
223 { ovf::CIMOSType_CIMOS_Debian, VBOXOSTYPE_Debian11 },
224 { ovf::CIMOSType_CIMOS_Debian_64, VBOXOSTYPE_Debian11_x64 },
225 { ovf::CIMOSType_CIMOS_Linux_2_4_x, VBOXOSTYPE_Linux24 },
226 { ovf::CIMOSType_CIMOS_Linux_2_4_x_64, VBOXOSTYPE_Linux24_x64 },
227 { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_Linux26 },
228 { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_Linux26_x64 },
229 { ovf::CIMOSType_CIMOS_Linux_64, VBOXOSTYPE_Linux26_x64 },
230
231 // types that we have support for but CIM doesn't
232 { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_ArchLinux },
233 { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_ArchLinux_x64 },
234 { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_FedoraCore },
235 { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_FedoraCore_x64 },
236 { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_Gentoo },
237 { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_Gentoo_x64 },
238 { ovf::CIMOSType_CIMOS_Linux_2_6_x, VBOXOSTYPE_Xandros },
239 { ovf::CIMOSType_CIMOS_Linux_2_6_x_64, VBOXOSTYPE_Xandros_x64 },
240 { ovf::CIMOSType_CIMOS_Solaris, VBOXOSTYPE_OpenSolaris },
241 { ovf::CIMOSType_CIMOS_Solaris_64, VBOXOSTYPE_OpenSolaris_x64 },
242
243 // types added with CIM 2.25.0 follow:
244 { ovf::CIMOSType_CIMOS_WindowsServer2008R2, VBOXOSTYPE_Win2k8 }, // duplicate, see above
245// { ovf::CIMOSType_CIMOS_VMwareESXi = 104, // we can't run ESX in a VM
246 { ovf::CIMOSType_CIMOS_Windows7, VBOXOSTYPE_Win7 },
247 { ovf::CIMOSType_CIMOS_Windows7, VBOXOSTYPE_Win7_x64 }, // there is no
248 // CIM 64-bit type for this
249 { ovf::CIMOSType_CIMOS_CentOS, VBOXOSTYPE_RedHat },
250 { ovf::CIMOSType_CIMOS_CentOS_64, VBOXOSTYPE_RedHat_x64 },
251 { ovf::CIMOSType_CIMOS_OracleLinux, VBOXOSTYPE_Oracle },
252 { ovf::CIMOSType_CIMOS_OracleLinux_64, VBOXOSTYPE_Oracle_x64 },
253 { ovf::CIMOSType_CIMOS_OracleLinux, VBOXOSTYPE_Oracle4 },
254 { ovf::CIMOSType_CIMOS_OracleLinux_64, VBOXOSTYPE_Oracle4_x64 },
255 { ovf::CIMOSType_CIMOS_OracleLinux, VBOXOSTYPE_Oracle5 },
256 { ovf::CIMOSType_CIMOS_OracleLinux_64, VBOXOSTYPE_Oracle5_x64 },
257 { ovf::CIMOSType_CIMOS_OracleLinux, VBOXOSTYPE_Oracle6 },
258 { ovf::CIMOSType_CIMOS_OracleLinux_64, VBOXOSTYPE_Oracle6_x64 },
259 { ovf::CIMOSType_CIMOS_OracleLinux_64, VBOXOSTYPE_Oracle7_x64 }, // 64-bit only
260 { ovf::CIMOSType_CIMOS_OracleLinux_64, VBOXOSTYPE_Oracle8_x64 }, // 64-bit only
261 { ovf::CIMOSType_CIMOS_eComStation, VBOXOSTYPE_ECS },
262
263 { ovf::CIMOSType_CIMOS_WindowsServer2011, VBOXOSTYPE_Win2k8_x64 }, // no 1:1 match on the VBox side
264 { ovf::CIMOSType_CIMOS_WindowsServer2012, VBOXOSTYPE_Win2k12_x64 },
265 { ovf::CIMOSType_CIMOS_Windows8, VBOXOSTYPE_Win8 },
266 { ovf::CIMOSType_CIMOS_Windows8_64, VBOXOSTYPE_Win8_x64 },
267 { ovf::CIMOSType_CIMOS_WindowsServer2012R2, VBOXOSTYPE_Win2k12_x64 },
268 { ovf::CIMOSType_CIMOS_Windows8_1, VBOXOSTYPE_Win81 },
269 { ovf::CIMOSType_CIMOS_Windows8_1_64, VBOXOSTYPE_Win81_x64 },
270 { ovf::CIMOSType_CIMOS_WindowsServer2016, VBOXOSTYPE_Win2k16_x64 },
271 { ovf::CIMOSType_CIMOS_Windows10, VBOXOSTYPE_Win10 },
272 { ovf::CIMOSType_CIMOS_Windows10_64, VBOXOSTYPE_Win10_x64 },
273 { ovf::CIMOSType_CIMOS_Windows10_64, VBOXOSTYPE_Win10_x64 },
274 { ovf::CIMOSType_CIMOS_WindowsServer2016, VBOXOSTYPE_Win2k19_x64 }, // no CIM type for this yet
275
276 // there are no CIM types for these, so these turn to "other" on export:
277 // VBOXOSTYPE_OpenBSD
278 // VBOXOSTYPE_OpenBSD_x64
279 // VBOXOSTYPE_NetBSD
280 // VBOXOSTYPE_NetBSD_x64
281
282};
283
284/* Pattern structure for matching the OS type description field */
285struct osTypePattern
286{
287 const char *pcszPattern;
288 VBOXOSTYPE osType;
289};
290
291/* These are the 32-Bit ones. They are sorted by priority. */
292static const osTypePattern g_aOsTypesPattern[] =
293{
294 {"Windows NT", VBOXOSTYPE_WinNT4},
295 {"Windows XP", VBOXOSTYPE_WinXP},
296 {"Windows 2000", VBOXOSTYPE_Win2k},
297 {"Windows 2003", VBOXOSTYPE_Win2k3},
298 {"Windows Vista", VBOXOSTYPE_WinVista},
299 {"Windows 2008", VBOXOSTYPE_Win2k8},
300 {"Windows 7", VBOXOSTYPE_Win7},
301 {"Windows 8.1", VBOXOSTYPE_Win81},
302 {"Windows 8", VBOXOSTYPE_Win8},
303 {"Windows 10", VBOXOSTYPE_Win10},
304 {"SUSE", VBOXOSTYPE_OpenSUSE},
305 {"Novell", VBOXOSTYPE_OpenSUSE},
306 {"Red Hat", VBOXOSTYPE_RedHat},
307 {"Mandriva", VBOXOSTYPE_Mandriva},
308 {"Ubuntu", VBOXOSTYPE_Ubuntu},
309 {"Debian", VBOXOSTYPE_Debian},
310 {"QNX", VBOXOSTYPE_QNX},
311 {"Linux 2.4", VBOXOSTYPE_Linux24},
312 {"Linux 2.6", VBOXOSTYPE_Linux26},
313 {"Linux", VBOXOSTYPE_Linux},
314 {"OpenSolaris", VBOXOSTYPE_OpenSolaris},
315 {"Solaris", VBOXOSTYPE_OpenSolaris},
316 {"FreeBSD", VBOXOSTYPE_FreeBSD},
317 {"NetBSD", VBOXOSTYPE_NetBSD},
318 {"Windows 95", VBOXOSTYPE_Win95},
319 {"Windows 98", VBOXOSTYPE_Win98},
320 {"Windows Me", VBOXOSTYPE_WinMe},
321 {"Windows 3.", VBOXOSTYPE_Win31},
322 {"DOS", VBOXOSTYPE_DOS},
323 {"OS2", VBOXOSTYPE_OS2}
324};
325
326/* These are the 64-Bit ones. They are sorted by priority. */
327static const osTypePattern g_aOsTypesPattern64[] =
328{
329 {"Windows XP", VBOXOSTYPE_WinXP_x64},
330 {"Windows 2003", VBOXOSTYPE_Win2k3_x64},
331 {"Windows Vista", VBOXOSTYPE_WinVista_x64},
332 {"Windows 2008", VBOXOSTYPE_Win2k8_x64},
333 {"Windows 7", VBOXOSTYPE_Win7_x64},
334 {"Windows 8.1", VBOXOSTYPE_Win81_x64},
335 {"Windows 8", VBOXOSTYPE_Win8_x64},
336 {"Windows 2012", VBOXOSTYPE_Win2k12_x64},
337 {"Windows 10", VBOXOSTYPE_Win10_x64},
338 {"Windows 2016", VBOXOSTYPE_Win2k16_x64},
339 {"Windows 2019", VBOXOSTYPE_Win2k19_x64},
340 {"SUSE", VBOXOSTYPE_OpenSUSE_x64},
341 {"Novell", VBOXOSTYPE_OpenSUSE_x64},
342 {"Red Hat", VBOXOSTYPE_RedHat_x64},
343 {"Mandriva", VBOXOSTYPE_Mandriva_x64},
344 {"Ubuntu", VBOXOSTYPE_Ubuntu_x64},
345 {"Debian", VBOXOSTYPE_Debian_x64},
346 {"Linux 2.4", VBOXOSTYPE_Linux24_x64},
347 {"Linux 2.6", VBOXOSTYPE_Linux26_x64},
348 {"Linux", VBOXOSTYPE_Linux26_x64},
349 {"OpenSolaris", VBOXOSTYPE_OpenSolaris_x64},
350 {"Solaris", VBOXOSTYPE_OpenSolaris_x64},
351 {"FreeBSD", VBOXOSTYPE_FreeBSD_x64},
352};
353
354/**
355 * Private helper func that suggests a VirtualBox guest OS type
356 * for the given OVF operating system type.
357 */
358void convertCIMOSType2VBoxOSType(Utf8Str &strType, ovf::CIMOSType_T c, const Utf8Str &cStr)
359{
360 /* First check if the type is other/other_64 */
361 if (c == ovf::CIMOSType_CIMOS_Other)
362 {
363 for (size_t i = 0; i < RT_ELEMENTS(g_aOsTypesPattern); ++i)
364 if (cStr.contains(g_aOsTypesPattern[i].pcszPattern, Utf8Str::CaseInsensitive))
365 {
366 strType = Global::OSTypeId(g_aOsTypesPattern[i].osType);
367 return;
368 }
369 }
370 else if (c == ovf::CIMOSType_CIMOS_Other_64)
371 {
372 for (size_t i = 0; i < RT_ELEMENTS(g_aOsTypesPattern64); ++i)
373 if (cStr.contains(g_aOsTypesPattern64[i].pcszPattern, Utf8Str::CaseInsensitive))
374 {
375 strType = Global::OSTypeId(g_aOsTypesPattern64[i].osType);
376 return;
377 }
378 }
379
380 for (size_t i = 0; i < RT_ELEMENTS(g_aOsTypes); ++i)
381 {
382 if (c == g_aOsTypes[i].cim)
383 {
384 strType = Global::OSTypeId(g_aOsTypes[i].osType);
385 return;
386 }
387 }
388
389 if (c == ovf::CIMOSType_CIMOS_Other_64)
390 strType = Global::OSTypeId(VBOXOSTYPE_Unknown_x64);
391 else
392 strType = Global::OSTypeId(VBOXOSTYPE_Unknown);
393}
394
395/**
396 * Private helper func that suggests a VirtualBox guest OS type
397 * for the given OVF operating system type.
398 * @returns CIM OS type.
399 * @param pcszVBox Our guest OS type identifier string.
400 * @param fLongMode Whether long mode is enabled and a 64-bit CIM type is
401 * preferred even if the VBox guest type isn't 64-bit.
402 */
403ovf::CIMOSType_T convertVBoxOSType2CIMOSType(const char *pcszVBox, BOOL fLongMode)
404{
405 for (size_t i = 0; i < RT_ELEMENTS(g_aOsTypes); ++i)
406 {
407 if (!RTStrICmp(pcszVBox, Global::OSTypeId(g_aOsTypes[i].osType)))
408 {
409 if (fLongMode && !(g_aOsTypes[i].osType & VBOXOSTYPE_x64))
410 {
411 VBOXOSTYPE enmDesiredOsType = (VBOXOSTYPE)((int)g_aOsTypes[i].osType | (int)VBOXOSTYPE_x64);
412 for (size_t j = i+1; j < RT_ELEMENTS(g_aOsTypes); j++)
413 if (g_aOsTypes[j].osType == enmDesiredOsType)
414 return g_aOsTypes[j].cim;
415 if (i > 0)
416 {
417 for (size_t j = i-1; j > 0; j++)
418 if (g_aOsTypes[j].osType == enmDesiredOsType)
419 return g_aOsTypes[j].cim;
420 }
421 /* Not all OSes have 64-bit versions, so just return the 32-bit variant. */
422 }
423 return g_aOsTypes[i].cim;
424 }
425 }
426
427 return fLongMode ? ovf::CIMOSType_CIMOS_Other_64 : ovf::CIMOSType_CIMOS_Other;
428}
429
430Utf8Str convertNetworkAttachmentTypeToString(NetworkAttachmentType_T type)
431{
432 Utf8Str strType;
433 switch (type)
434 {
435 case NetworkAttachmentType_NAT: strType = "NAT"; break;
436 case NetworkAttachmentType_Bridged: strType = "Bridged"; break;
437 case NetworkAttachmentType_Internal: strType = "Internal"; break;
438 case NetworkAttachmentType_HostOnly: strType = "HostOnly"; break;
439 case NetworkAttachmentType_HostOnlyNetwork: strType = "HostOnlyNetwork"; break;
440 case NetworkAttachmentType_Generic: strType = "Generic"; break;
441 case NetworkAttachmentType_NATNetwork: strType = "NATNetwork"; break;
442 case NetworkAttachmentType_Null: strType = "Null"; break;
443 case NetworkAttachmentType_Cloud: strType = "Cloud"; break;
444#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
445 case NetworkAttachmentType_32BitHack: AssertFailedBreak(); /* (compiler warnings) */
446#endif
447 }
448 return strType;
449}
450
451
452////////////////////////////////////////////////////////////////////////////////
453//
454// Appliance constructor / destructor
455//
456// ////////////////////////////////////////////////////////////////////////////////
457
458DEFINE_EMPTY_CTOR_DTOR(VirtualSystemDescription)
459
460HRESULT VirtualSystemDescription::FinalConstruct()
461{
462 return BaseFinalConstruct();
463}
464
465void VirtualSystemDescription::FinalRelease()
466{
467 uninit();
468
469 BaseFinalRelease();
470}
471
472Appliance::Appliance()
473 : mVirtualBox(NULL)
474{
475}
476
477Appliance::~Appliance()
478{
479}
480
481
482HRESULT Appliance::FinalConstruct()
483{
484 return BaseFinalConstruct();
485}
486
487void Appliance::FinalRelease()
488{
489 uninit();
490
491 BaseFinalRelease();
492}
493
494
495////////////////////////////////////////////////////////////////////////////////
496//
497// Internal helpers
498//
499////////////////////////////////////////////////////////////////////////////////
500
501
502////////////////////////////////////////////////////////////////////////////////
503//
504// IVirtualBox public methods
505//
506////////////////////////////////////////////////////////////////////////////////
507
508// This code is here so we won't have to include the appliance headers in the
509// IVirtualBox implementation.
510
511/**
512 * Implementation for IVirtualBox::createAppliance.
513 *
514 * @param aAppliance IAppliance object created if S_OK is returned.
515 * @return S_OK or error.
516 */
517HRESULT VirtualBox::createAppliance(ComPtr<IAppliance> &aAppliance)
518{
519 ComObjPtr<Appliance> appliance;
520 HRESULT hrc = appliance.createObject();
521 if (SUCCEEDED(hrc))
522 {
523 hrc = appliance->init(this);
524 if (SUCCEEDED(hrc))
525 hrc = appliance.queryInterfaceTo(aAppliance.asOutParam());
526 }
527 return hrc;
528}
529
530/**
531 * Appliance COM initializer.
532 * @param aVirtualBox The VirtualBox object.
533 */
534HRESULT Appliance::init(VirtualBox *aVirtualBox)
535{
536 HRESULT rc = S_OK;
537 /* Enclose the state transition NotReady->InInit->Ready */
538 AutoInitSpan autoInitSpan(this);
539 AssertReturn(autoInitSpan.isOk(), E_FAIL);
540
541 /* Weak reference to a VirtualBox object */
542 unconst(mVirtualBox) = aVirtualBox;
543
544 // initialize data
545 m = new Data;
546 m->m_pSecretKeyStore = new SecretKeyStore(false /* fRequireNonPageable*/);
547 AssertReturn(m->m_pSecretKeyStore, E_FAIL);
548
549 rc = i_initBackendNames();
550
551 /* Confirm a successful initialization */
552 autoInitSpan.setSucceeded();
553
554 return rc;
555}
556
557/**
558 * Appliance COM uninitializer.
559 */
560void Appliance::uninit()
561{
562 /* Enclose the state transition Ready->InUninit->NotReady */
563 AutoUninitSpan autoUninitSpan(this);
564 if (autoUninitSpan.uninitDone())
565 return;
566
567 if (m->m_pSecretKeyStore)
568 delete m->m_pSecretKeyStore;
569
570 delete m;
571 m = NULL;
572}
573
574////////////////////////////////////////////////////////////////////////////////
575//
576// IAppliance public methods
577//
578////////////////////////////////////////////////////////////////////////////////
579
580/**
581 * Public method implementation.
582 */
583HRESULT Appliance::getPath(com::Utf8Str &aPath)
584{
585 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
586
587 aPath = m->locInfo.strPath;
588
589 return S_OK;
590}
591
592/**
593 * Public method implementation.
594 */
595HRESULT Appliance::getDisks(std::vector<com::Utf8Str> &aDisks)
596{
597 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
598
599 aDisks.resize(0);
600
601 if (m->pReader) // OVFReader instantiated?
602 {
603 aDisks.resize(m->pReader->m_mapDisks.size());
604
605 ovf::DiskImagesMap::const_iterator it;
606 size_t i = 0;
607 for (it = m->pReader->m_mapDisks.begin();
608 it != m->pReader->m_mapDisks.end();
609 ++it, ++i)
610 {
611 // create a string representing this disk
612 const ovf::DiskImage &d = it->second;
613 char *psz = NULL;
614 RTStrAPrintf(&psz,
615 "%s\t"
616 "%RI64\t"
617 "%RI64\t"
618 "%s\t"
619 "%s\t"
620 "%RI64\t"
621 "%RI64\t"
622 "%s",
623 d.strDiskId.c_str(),
624 d.iCapacity,
625 d.iPopulatedSize,
626 d.strFormat.c_str(),
627 d.strHref.c_str(),
628 d.iSize,
629 d.iChunkSize,
630 d.strCompression.c_str());
631 Utf8Str utf(psz);
632 aDisks[i] = utf;
633 RTStrFree(psz);
634 }
635 }
636
637 return S_OK;
638}
639
640/**
641 * Public method implementation.
642 */
643HRESULT Appliance::getCertificate(ComPtr<ICertificate> &aCertificateInfo)
644{
645 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
646
647 /* Can be NULL at this point, queryInterfaceto handles that. */
648 m->ptrCertificateInfo.queryInterfaceTo(aCertificateInfo.asOutParam());
649 return S_OK;
650}
651
652/**
653 * Public method implementation.
654 */
655HRESULT Appliance::getVirtualSystemDescriptions(std::vector<ComPtr<IVirtualSystemDescription> > &aVirtualSystemDescriptions)
656{
657 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
658
659 aVirtualSystemDescriptions.resize(m->virtualSystemDescriptions.size());
660 std::list< ComObjPtr<VirtualSystemDescription> > vsds(m->virtualSystemDescriptions);
661 size_t i = 0;
662 for (std::list< ComObjPtr<VirtualSystemDescription> >::iterator it = vsds.begin(); it != vsds.end(); ++it, ++i)
663 {
664 (*it).queryInterfaceTo(aVirtualSystemDescriptions[i].asOutParam());
665 }
666 return S_OK;
667}
668
669/**
670 * Public method implementation.
671 */
672HRESULT Appliance::getMachines(std::vector<com::Utf8Str> &aMachines)
673{
674 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
675
676 aMachines.resize(m->llGuidsMachinesCreated.size());
677 size_t i = 0;
678 for (std::list<Guid>::const_iterator it = m->llGuidsMachinesCreated.begin();
679 it != m->llGuidsMachinesCreated.end();
680 ++it, ++i)
681 {
682 const Guid &uuid = *it;
683 aMachines[i] = uuid.toUtf16();
684 }
685 return S_OK;
686}
687
688HRESULT Appliance::createVFSExplorer(const com::Utf8Str &aURI, ComPtr<IVFSExplorer> &aExplorer)
689{
690 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
691
692 ComObjPtr<VFSExplorer> explorer;
693 HRESULT rc = S_OK;
694 try
695 {
696 Utf8Str uri(aURI);
697 /* Check which kind of export the user has requested */
698 LocationInfo li;
699 i_parseURI(aURI, li);
700 /* Create the explorer object */
701 explorer.createObject();
702 rc = explorer->init(li.storageType, li.strPath, li.strHostname, li.strUsername, li.strPassword, mVirtualBox);
703 }
704 catch (HRESULT aRC)
705 {
706 rc = aRC;
707 }
708
709 if (SUCCEEDED(rc))
710 /* Return explorer to the caller */
711 explorer.queryInterfaceTo(aExplorer.asOutParam());
712
713 return rc;
714}
715
716
717/**
718 * Public method implementation.
719 * Add the "aRequested" numbers of new empty objects of VSD into the list
720 * "virtualSystemDescriptions".
721 * The parameter "aCreated" keeps the actual number of the added objects.
722 * In case of exception all added objects are removed from the list.
723 */
724HRESULT Appliance::createVirtualSystemDescriptions(ULONG aRequested, ULONG *aCreated)
725{
726 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
727
728 HRESULT rc = S_OK;
729 uint32_t lQuantity = aRequested;
730 uint32_t i=0;
731
732 if (lQuantity < 1)
733 return setError(E_FAIL, tr("The number of VirtualSystemDescription objects must be at least 1 or more."));
734 try
735 {
736 for (; i<lQuantity; ++i)
737 {
738 ComObjPtr<VirtualSystemDescription> opVSD;
739 rc = opVSD.createObject();
740 if (SUCCEEDED(rc))
741 {
742 rc = opVSD->init();
743 if (SUCCEEDED(rc))
744 m->virtualSystemDescriptions.push_back(opVSD);
745 else
746 break;
747 }
748 else
749 break;
750 }
751
752 if (i<lQuantity)
753 LogRel(("Number of created VirtualSystemDescription objects is less than requested"
754 "(Requested %d, Created %d)",lQuantity, i));
755
756 *aCreated = i;
757 }
758 catch (HRESULT aRC)
759 {
760 for (; i>0; --i)
761 {
762 if (!m->virtualSystemDescriptions.empty())
763 m->virtualSystemDescriptions.pop_back();
764 else
765 break;
766 }
767 rc = aRC;
768 }
769
770 return rc;
771}
772
773/**
774 * Public method implementation.
775 */
776HRESULT Appliance::getWarnings(std::vector<com::Utf8Str> &aWarnings)
777{
778 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
779
780 aWarnings.resize(m->llWarnings.size());
781
782 list<Utf8Str>::const_iterator it;
783 size_t i = 0;
784 for (it = m->llWarnings.begin();
785 it != m->llWarnings.end();
786 ++it, ++i)
787 {
788 aWarnings[i] = *it;
789 }
790
791 return S_OK;
792}
793
794HRESULT Appliance::getPasswordIds(std::vector<com::Utf8Str> &aIdentifiers)
795{
796 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
797
798 aIdentifiers = m->m_vecPasswordIdentifiers;
799 return S_OK;
800}
801
802HRESULT Appliance::getMediumIdsForPasswordId(const com::Utf8Str &aPasswordId, std::vector<com::Guid> &aIdentifiers)
803{
804 HRESULT hrc = S_OK;
805 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
806
807 std::map<com::Utf8Str, GUIDVEC>::const_iterator it = m->m_mapPwIdToMediumIds.find(aPasswordId);
808 if (it != m->m_mapPwIdToMediumIds.end())
809 aIdentifiers = it->second;
810 else
811 hrc = setError(E_FAIL, tr("The given password identifier is not associated with any medium"));
812
813 return hrc;
814}
815
816HRESULT Appliance::addPasswords(const std::vector<com::Utf8Str> &aIdentifiers,
817 const std::vector<com::Utf8Str> &aPasswords)
818{
819 HRESULT hrc = S_OK;
820
821 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
822
823 /* Check that the IDs do not exist already before changing anything. */
824 for (unsigned i = 0; i < aIdentifiers.size(); i++)
825 {
826 SecretKey *pKey = NULL;
827 int rc = m->m_pSecretKeyStore->retainSecretKey(aIdentifiers[i], &pKey);
828 if (rc != VERR_NOT_FOUND)
829 {
830 AssertPtr(pKey);
831 if (pKey)
832 pKey->release();
833 return setError(VBOX_E_OBJECT_IN_USE, tr("A password with the given ID already exists"));
834 }
835 }
836
837 for (unsigned i = 0; i < aIdentifiers.size() && SUCCEEDED(hrc); i++)
838 {
839 size_t cbKey = aPasswords[i].length() + 1; /* Include terminator */
840 const uint8_t *pbKey = (const uint8_t *)aPasswords[i].c_str();
841
842 int rc = m->m_pSecretKeyStore->addSecretKey(aIdentifiers[i], pbKey, cbKey);
843 if (RT_SUCCESS(rc))
844 m->m_cPwProvided++;
845 else if (rc == VERR_NO_MEMORY)
846 hrc = setError(E_OUTOFMEMORY, tr("Failed to allocate enough secure memory for the key"));
847 else
848 hrc = setError(E_FAIL, tr("Unknown error happened while adding a password (%Rrc)"), rc);
849 }
850
851 return hrc;
852}
853
854////////////////////////////////////////////////////////////////////////////////
855//
856// Appliance private methods
857//
858////////////////////////////////////////////////////////////////////////////////
859
860HRESULT Appliance::i_initBackendNames()
861{
862 HRESULT hrc = S_OK;
863 if (!g_fInitializedBackendNames)
864 {
865 /*
866 * Use the system properties to translate file extensions into
867 * storage backend names.
868 */
869 static struct
870 {
871 const char *pszExt; /**< extension */
872 char *pszBackendName;
873 size_t cbBackendName;
874 } const s_aFormats[] =
875 {
876 { "iso", g_szIsoBackend, sizeof(g_szIsoBackend) },
877 { "vmdk", g_szVmdkBackend, sizeof(g_szVmdkBackend) },
878 { "vhd", g_szVhdBackend, sizeof(g_szVhdBackend) },
879 };
880 SystemProperties *pSysProps = mVirtualBox->i_getSystemProperties();
881 for (unsigned i = 0; i < RT_ELEMENTS(s_aFormats); i++)
882 {
883 ComObjPtr<MediumFormat> trgFormat = pSysProps->i_mediumFormatFromExtension(s_aFormats[i].pszExt);
884 if (trgFormat.isNotNull())
885 {
886 const char *pszName = trgFormat->i_getName().c_str();
887 int vrc = RTStrCopy(s_aFormats[i].pszBackendName, s_aFormats[i].cbBackendName, pszName);
888 AssertRCStmt(vrc, hrc = setError(E_FAIL, "Unexpected storage backend name copy error %Rrc for %s.", vrc, pszName));
889 }
890 else
891 hrc = setError(E_FAIL, tr("Can't find appropriate medium format for ISO type of a virtual disk."));
892 }
893
894 if (SUCCEEDED(hrc))
895 g_fInitializedBackendNames = true;
896 }
897
898 return hrc;
899}
900
901Utf8Str Appliance::i_typeOfVirtualDiskFormatFromURI(Utf8Str uri) const
902{
903 Assert(g_fInitializedBackendNames);
904
905 unsigned i = RT_ELEMENTS(g_aUriToBackend);
906 while (i-- > 0)
907 if (RTStrICmp(g_aUriToBackend[i].pszUri, uri.c_str()) == 0)
908 return Utf8Str(g_aUriToBackend[i].pszBackend);
909 return Utf8Str();
910}
911
912#if 0 /* unused */
913std::set<Utf8Str> Appliance::i_URIFromTypeOfVirtualDiskFormat(Utf8Str type)
914{
915 Assert(g_fInitializedBackendNames);
916
917 std::set<Utf8Str> UriSet;
918 unsigned i = RT_ELEMENTS(g_aUriToBackend);
919 while (i-- > 0)
920 if (RTStrICmp(g_aUriToBackend[i].pszBackend, type.c_str()) == 0)
921 UriSet.insert(g_aUriToBackend[i].pszUri);
922 return UriSet;
923}
924#endif
925
926/**
927 * Returns a medium format object corresponding to the given
928 * disk image or null if no such format.
929 *
930 * @param di Disk Image
931 * @param mf Medium Format
932 *
933 * @return ComObjPtr<MediumFormat>
934 */
935HRESULT Appliance::i_findMediumFormatFromDiskImage(const ovf::DiskImage &di, ComObjPtr<MediumFormat>& mf)
936{
937 HRESULT rc = S_OK;
938
939 /* Get the system properties. */
940 SystemProperties *pSysProps = mVirtualBox->i_getSystemProperties();
941
942 /* We need a proper source format description */
943 /* Which format to use? */
944 Utf8Str strSrcFormat = i_typeOfVirtualDiskFormatFromURI(di.strFormat);
945
946 /*
947 * fallback, if we can't determine virtual disk format using URI from the attribute ovf:format
948 * in the corresponding section <Disk> in the OVF file.
949 */
950 if (strSrcFormat.isEmpty())
951 {
952 strSrcFormat = di.strHref;
953
954 /* check either file gzipped or not
955 * if "yes" then remove last extension,
956 * i.e. "image.vmdk.gz"->"image.vmdk"
957 */
958 if (di.strCompression == "gzip")
959 {
960 if (RTPathHasSuffix(strSrcFormat.c_str()))
961 {
962 strSrcFormat.stripSuffix();
963 }
964 else
965 {
966 mf.setNull();
967 rc = setError(E_FAIL,
968 tr("Internal inconsistency looking up medium format for the disk image '%s'"),
969 di.strHref.c_str());
970 return rc;
971 }
972 }
973 /* Figure out from extension which format the image of disk has. */
974 if (RTPathHasSuffix(strSrcFormat.c_str()))
975 {
976 const char *pszExt = RTPathSuffix(strSrcFormat.c_str());
977 if (pszExt)
978 pszExt++;
979 mf = pSysProps->i_mediumFormatFromExtension(pszExt);
980 }
981 else
982 mf.setNull();
983 }
984 else
985 mf = pSysProps->i_mediumFormat(strSrcFormat);
986
987 if (mf.isNull())
988 rc = setError(E_FAIL, tr("Internal inconsistency looking up medium format for the disk image '%s'"),
989 di.strHref.c_str());
990
991 return rc;
992}
993
994/**
995 * Setup automatic I/O stream digest calculation, adding it to hOurManifest.
996 *
997 * @returns Passthru I/O stream, of @a hVfsIos if no digest calc needed.
998 * @param hVfsIos The stream to wrap. Always consumed.
999 * @param pszManifestEntry The manifest entry.
1000 * @param fRead Set if read stream, clear if write.
1001 * @throws Nothing.
1002 */
1003RTVFSIOSTREAM Appliance::i_manifestSetupDigestCalculationForGivenIoStream(RTVFSIOSTREAM hVfsIos, const char *pszManifestEntry,
1004 bool fRead /*= true */)
1005{
1006 int vrc;
1007 Assert(!RTManifestPtIosIsInstanceOf(hVfsIos));
1008
1009 if (m->fDigestTypes == 0)
1010 return hVfsIos;
1011
1012 /* Create the manifest if necessary. */
1013 if (m->hOurManifest == NIL_RTMANIFEST)
1014 {
1015 vrc = RTManifestCreate(0 /*fFlags*/, &m->hOurManifest);
1016 AssertRCReturnStmt(vrc, RTVfsIoStrmRelease(hVfsIos), NIL_RTVFSIOSTREAM);
1017 }
1018
1019 /* Setup the stream. */
1020 RTVFSIOSTREAM hVfsIosPt;
1021 vrc = RTManifestEntryAddPassthruIoStream(m->hOurManifest, hVfsIos, pszManifestEntry, m->fDigestTypes, fRead, &hVfsIosPt);
1022
1023 RTVfsIoStrmRelease(hVfsIos); /* always consumed! */
1024 if (RT_SUCCESS(vrc))
1025 return hVfsIosPt;
1026
1027 setErrorVrc(vrc, tr("RTManifestEntryAddPassthruIoStream failed with rc=%Rrc"), vrc);
1028 return NIL_RTVFSIOSTREAM;
1029}
1030
1031/**
1032 * Returns true if the appliance is in "idle" state. This should always be the
1033 * case unless an import or export is currently in progress. Similar to machine
1034 * states, this permits the Appliance implementation code to let go of the
1035 * Appliance object lock while a time-consuming disk conversion is in progress
1036 * without exposing the appliance to conflicting calls.
1037 *
1038 * This sets an error on "this" (the appliance) and returns false if the appliance
1039 * is busy. The caller should then return E_ACCESSDENIED.
1040 *
1041 * Must be called from under the object lock!
1042 */
1043bool Appliance::i_isApplianceIdle()
1044{
1045 if (m->state == ApplianceImporting)
1046 setError(VBOX_E_INVALID_OBJECT_STATE, tr("The appliance is busy importing files"));
1047 else if (m->state == ApplianceExporting)
1048 setError(VBOX_E_INVALID_OBJECT_STATE, tr("The appliance is busy exporting files"));
1049 else
1050 return true;
1051
1052 return false;
1053}
1054
1055HRESULT Appliance::i_searchUniqueVMName(Utf8Str &aName) const
1056{
1057 ComPtr<IMachine> ptrMachine;
1058 char *tmpName = RTStrDup(aName.c_str());
1059 int i = 1;
1060 while (mVirtualBox->FindMachine(Bstr(tmpName).raw(), ptrMachine.asOutParam()) != VBOX_E_OBJECT_NOT_FOUND)
1061 {
1062 RTStrFree(tmpName);
1063 RTStrAPrintf(&tmpName, "%s %d", aName.c_str(), i);
1064 ++i;
1065 }
1066 aName = tmpName;
1067 RTStrFree(tmpName);
1068
1069 return S_OK;
1070}
1071
1072HRESULT Appliance::i_ensureUniqueImageFilePath(const Utf8Str &aMachineFolder, DeviceType_T aDeviceType, Utf8Str &aName) const
1073{
1074 /*
1075 * Check if the file exists or if a medium with this path is registered already
1076 */
1077 Utf8Str strAbsName;
1078 size_t offDashNum = ~(size_t)0;
1079 size_t cchDashNum = 0;
1080 for (unsigned i = 1;; i++)
1081 {
1082 /* Complete the path (could be relative to machine folder). */
1083 int rc = RTPathAbsExCxx(strAbsName, aMachineFolder, aName);
1084 AssertRCReturn(rc, Global::vboxStatusCodeToCOM(rc)); /** @todo stupid caller ignores this */
1085
1086 /* Check that the file does not exist and that there is no media somehow matching the name. */
1087 if (!RTPathExists(strAbsName.c_str()))
1088 {
1089 ComPtr<IMedium> ptrMedium;
1090 HRESULT hrc = mVirtualBox->OpenMedium(Bstr(strAbsName).raw(), aDeviceType, AccessMode_ReadWrite,
1091 FALSE /* fForceNewUuid */, ptrMedium.asOutParam());
1092 if (hrc == VBOX_E_OBJECT_NOT_FOUND)
1093 return S_OK;
1094 }
1095
1096 /* Insert '_%i' before the suffix and try again. */
1097 if (offDashNum == ~(size_t)0)
1098 {
1099 const char *pszSuffix = RTPathSuffix(aName.c_str());
1100 offDashNum = pszSuffix ? (size_t)(pszSuffix - aName.c_str()) : aName.length();
1101 }
1102 char szTmp[32];
1103 size_t cchTmp = RTStrPrintf(szTmp, sizeof(szTmp), "_%u", i);
1104 aName.replace(offDashNum, cchDashNum, szTmp, cchTmp);
1105 cchDashNum = cchTmp;
1106 }
1107}
1108
1109/**
1110 * Called from Appliance::importImpl() and Appliance::writeImpl() to set up a
1111 * progress object with the proper weights and maximum progress values.
1112 */
1113HRESULT Appliance::i_setUpProgress(ComObjPtr<Progress> &pProgress,
1114 const Utf8Str &strDescription,
1115 SetUpProgressMode mode)
1116{
1117 HRESULT rc;
1118
1119 /* Create the progress object */
1120 try
1121 {
1122 rc = pProgress.createObject();
1123 if (FAILED(rc))
1124 return rc;
1125 }
1126 catch (std::bad_alloc &)
1127 {
1128 return E_OUTOFMEMORY;
1129 }
1130
1131 // compute the disks weight (this sets ulTotalDisksMB and cDisks in the instance data)
1132 i_disksWeight();
1133
1134 m->ulWeightForManifestOperation = 0;
1135
1136 ULONG cOperations = 1 // one for XML setup
1137 + m->cDisks; // plus one per disk
1138 ULONG ulTotalOperationsWeight;
1139 if (m->ulTotalDisksMB)
1140 {
1141 m->ulWeightForXmlOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress for the XML
1142 ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightForXmlOperation;
1143 }
1144 else
1145 {
1146 // no disks to export:
1147 m->ulWeightForXmlOperation = 1;
1148 ulTotalOperationsWeight = 1;
1149 }
1150
1151 switch (mode)
1152 {
1153 case ImportFile:
1154 {
1155 break;
1156 }
1157 case WriteFile:
1158 {
1159 // assume that creating the manifest will take .1% of the time it takes to export the disks
1160 if (m->fManifest)
1161 {
1162 ++cOperations; // another one for creating the manifest
1163
1164 m->ulWeightForManifestOperation = (ULONG)((double)m->ulTotalDisksMB * .1 / 100); // use .5% of the
1165 // progress for the manifest
1166 ulTotalOperationsWeight += m->ulWeightForManifestOperation;
1167 }
1168 break;
1169 }
1170 case ImportS3:
1171 {
1172 cOperations += 1 + 1; // another one for the manifest file & another one for the import
1173 ulTotalOperationsWeight = m->ulTotalDisksMB;
1174 if (!m->ulTotalDisksMB)
1175 // no disks to export:
1176 ulTotalOperationsWeight = 1;
1177
1178 ULONG ulImportWeight = (ULONG)((double)ulTotalOperationsWeight * 50 / 100); // use 50% for import
1179 ulTotalOperationsWeight += ulImportWeight;
1180
1181 m->ulWeightForXmlOperation = ulImportWeight; /* save for using later */
1182
1183 ULONG ulInitWeight = (ULONG)((double)ulTotalOperationsWeight * 0.1 / 100); // use 0.1% for init
1184 ulTotalOperationsWeight += ulInitWeight;
1185 break;
1186 }
1187 case WriteS3:
1188 {
1189 cOperations += 1 + 1; // another one for the mf & another one for temporary creation
1190
1191 if (m->ulTotalDisksMB)
1192 {
1193 m->ulWeightForXmlOperation = (ULONG)((double)m->ulTotalDisksMB * 1 / 100); // use 1% of the progress
1194 // for OVF file upload
1195 // (we didn't know the
1196 // size at this point)
1197 ulTotalOperationsWeight = m->ulTotalDisksMB + m->ulWeightForXmlOperation;
1198 }
1199 else
1200 {
1201 // no disks to export:
1202 ulTotalOperationsWeight = 1;
1203 m->ulWeightForXmlOperation = 1;
1204 }
1205 ULONG ulOVFCreationWeight = (ULONG)((double)ulTotalOperationsWeight * 50.0 / 100.0); /* Use 50% for the
1206 creation of the OVF
1207 & the disks */
1208 ulTotalOperationsWeight += ulOVFCreationWeight;
1209 break;
1210 }
1211 case ExportCloud:
1212 case ImportCloud:
1213 break;
1214 }
1215 Log(("Setting up progress object: ulTotalMB = %d, cDisks = %d, => cOperations = %d, ulTotalOperationsWeight = %d, m->ulWeightForXmlOperation = %d\n",
1216 m->ulTotalDisksMB, m->cDisks, cOperations, ulTotalOperationsWeight, m->ulWeightForXmlOperation));
1217
1218 return pProgress->init(mVirtualBox, static_cast<IAppliance*>(this),
1219 strDescription,
1220 TRUE /* aCancelable */,
1221 cOperations, // ULONG cOperations,
1222 ulTotalOperationsWeight, // ULONG ulTotalOperationsWeight,
1223 strDescription, // CBSTR bstrFirstOperationDescription,
1224 m->ulWeightForXmlOperation); // ULONG ulFirstOperationWeight,
1225}
1226
1227void Appliance::i_addWarning(const char* aWarning, ...)
1228{
1229 try
1230 {
1231 va_list args;
1232 va_start(args, aWarning);
1233 Utf8Str str(aWarning, args);
1234 va_end(args);
1235 m->llWarnings.push_back(str);
1236 }
1237 catch (...)
1238 {
1239 AssertFailed();
1240 }
1241}
1242
1243/**
1244 * Refreshes the cDisks and ulTotalDisksMB members in the instance data.
1245 * Requires that virtual system descriptions are present.
1246 */
1247void Appliance::i_disksWeight()
1248{
1249 m->ulTotalDisksMB = 0;
1250 m->cDisks = 0;
1251 // weigh the disk images according to their sizes
1252 list< ComObjPtr<VirtualSystemDescription> >::const_iterator it;
1253 for (it = m->virtualSystemDescriptions.begin();
1254 it != m->virtualSystemDescriptions.end();
1255 ++it)
1256 {
1257 ComObjPtr<VirtualSystemDescription> vsdescThis = (*it);
1258 /* One for every medium of the Virtual System */
1259 std::list<VirtualSystemDescriptionEntry*> avsdeHDs = vsdescThis->i_findByType(VirtualSystemDescriptionType_HardDiskImage);
1260 std::list<VirtualSystemDescriptionEntry*>::const_iterator itH;
1261 for (itH = avsdeHDs.begin();
1262 itH != avsdeHDs.end();
1263 ++itH)
1264 {
1265 const VirtualSystemDescriptionEntry *pHD = *itH;
1266 m->ulTotalDisksMB += pHD->ulSizeMB;
1267 ++m->cDisks;
1268 }
1269
1270 avsdeHDs = vsdescThis->i_findByType(VirtualSystemDescriptionType_CDROM);
1271 for (itH = avsdeHDs.begin();
1272 itH != avsdeHDs.end();
1273 ++itH)
1274 {
1275 const VirtualSystemDescriptionEntry *pHD = *itH;
1276 m->ulTotalDisksMB += pHD->ulSizeMB;
1277 ++m->cDisks;
1278 }
1279 }
1280
1281}
1282
1283void Appliance::i_parseBucket(Utf8Str &aPath, Utf8Str &aBucket)
1284{
1285 /* Buckets are S3 specific. So parse the bucket out of the file path */
1286 if (!aPath.startsWith("/"))
1287 throw setError(E_INVALIDARG,
1288 tr("The path '%s' must start with /"), aPath.c_str());
1289 size_t bpos = aPath.find("/", 1);
1290 if (bpos != Utf8Str::npos)
1291 {
1292 aBucket = aPath.substr(1, bpos - 1); /* The bucket without any slashes */
1293 aPath = aPath.substr(bpos); /* The rest of the file path */
1294 }
1295 /* If there is no bucket name provided reject it */
1296 if (aBucket.isEmpty())
1297 throw setError(E_INVALIDARG,
1298 tr("You doesn't provide a bucket name in the URI '%s'"), aPath.c_str());
1299}
1300
1301/**
1302 * Worker for TaskOVF::handler.
1303 *
1304 * The TaskOVF is started in Appliance::readImpl() and Appliance::importImpl()
1305 * and Appliance::writeImpl().
1306 *
1307 * This will in turn call Appliance::readFS() or Appliance::importFS() or
1308 * Appliance::writeFS().
1309 *
1310 * @thread pTask The task.
1311 */
1312/* static */ void Appliance::i_importOrExportThreadTask(TaskOVF *pTask)
1313{
1314 LogFlowFuncEnter();
1315 AssertReturnVoid(pTask);
1316
1317 Appliance *pAppliance = pTask->pAppliance;
1318 LogFlowFunc(("Appliance %p taskType=%d\n", pAppliance, pTask->taskType));
1319
1320 switch (pTask->taskType)
1321 {
1322 case TaskOVF::Read:
1323 pAppliance->m->resetReadData();
1324 if (pTask->locInfo.storageType == VFSType_File)
1325 pTask->rc = pAppliance->i_readFS(pTask);
1326 else
1327 pTask->rc = E_NOTIMPL;
1328 break;
1329
1330 case TaskOVF::Import:
1331 /** @todo allow overriding these? */
1332 if (!pAppliance->m->fSignatureValid && pAppliance->m->pbSignedDigest)
1333 pTask->rc = pAppliance->setError(E_FAIL, tr("The manifest signature for '%s' is not valid"),
1334 pTask->locInfo.strPath.c_str());
1335 else if (!pAppliance->m->fCertificateValid && pAppliance->m->pbSignedDigest)
1336 {
1337 if (pAppliance->m->strCertError.isNotEmpty())
1338 pTask->rc = pAppliance->setError(E_FAIL, tr("The certificate used to signed '%s' is not valid: %s"),
1339 pTask->locInfo.strPath.c_str(), pAppliance->m->strCertError.c_str());
1340 else
1341 pTask->rc = pAppliance->setError(E_FAIL, tr("The certificate used to signed '%s' is not valid"),
1342 pTask->locInfo.strPath.c_str());
1343 }
1344 // fusion does not consider this a show stopper (we've filed a warning during read).
1345 //else if (pAppliance->m->fCertificateMissingPath && pAppliance->m->pbSignedDigest)
1346 // pTask->rc = pAppliance->setError(E_FAIL, tr("The certificate used to signed '%s' is does not have a valid CA path"),
1347 // pTask->locInfo.strPath.c_str());
1348 else
1349 {
1350 if (pTask->locInfo.storageType == VFSType_File)
1351 pTask->rc = pAppliance->i_importFS(pTask);
1352 else
1353 pTask->rc = E_NOTIMPL;
1354 }
1355 break;
1356
1357 case TaskOVF::Write:
1358 if (pTask->locInfo.storageType == VFSType_File)
1359 pTask->rc = pAppliance->i_writeFS(pTask);
1360 else
1361 pTask->rc = E_NOTIMPL;
1362 break;
1363
1364 default:
1365 AssertFailed();
1366 pTask->rc = E_FAIL;
1367 break;
1368 }
1369
1370 if (!pTask->pProgress.isNull())
1371 pTask->pProgress->i_notifyComplete(pTask->rc);
1372
1373 LogFlowFuncLeave();
1374}
1375
1376/* static */ DECLCALLBACK(int) Appliance::TaskOVF::updateProgress(unsigned uPercent, void *pvUser)
1377{
1378 Appliance::TaskOVF* pTask = *(Appliance::TaskOVF**)pvUser;
1379
1380 if ( pTask
1381 && !pTask->pProgress.isNull())
1382 {
1383 BOOL fCanceled;
1384 pTask->pProgress->COMGETTER(Canceled)(&fCanceled);
1385 if (fCanceled)
1386 return -1;
1387 pTask->pProgress->SetCurrentOperationProgress(uPercent);
1388 }
1389 return VINF_SUCCESS;
1390}
1391
1392/**
1393 * Worker for TaskOPC::handler.
1394 * @thread pTask The task.
1395 */
1396/* static */
1397void Appliance::i_exportOPCThreadTask(TaskOPC *pTask)
1398{
1399 LogFlowFuncEnter();
1400 AssertReturnVoid(pTask);
1401
1402 Appliance *pAppliance = pTask->pAppliance;
1403 LogFlowFunc(("Appliance %p taskType=%d\n", pAppliance, pTask->taskType));
1404
1405 switch (pTask->taskType)
1406 {
1407 case TaskOPC::Export:
1408 pTask->rc = pAppliance->i_writeFSOPC(pTask);
1409 break;
1410
1411 default:
1412 AssertFailed();
1413 pTask->rc = E_FAIL;
1414 break;
1415 }
1416
1417 if (!pTask->pProgress.isNull())
1418 pTask->pProgress->i_notifyComplete(pTask->rc);
1419
1420 LogFlowFuncLeave();
1421}
1422
1423/* static */
1424DECLCALLBACK(int) Appliance::TaskOPC::updateProgress(unsigned uPercent, void *pvUser)
1425{
1426 Appliance::TaskOPC* pTask = *(Appliance::TaskOPC**)pvUser;
1427
1428 if ( pTask
1429 && !pTask->pProgress.isNull())
1430 {
1431 BOOL fCanceled;
1432 pTask->pProgress->COMGETTER(Canceled)(&fCanceled);
1433 if (fCanceled)
1434 return -1;
1435 pTask->pProgress->SetCurrentOperationProgress(uPercent);
1436 }
1437 return VINF_SUCCESS;
1438}
1439
1440/**
1441 * Worker for TaskCloud::handler.
1442 * @thread pTask The task.
1443 */
1444/* static */
1445void Appliance::i_importOrExportCloudThreadTask(TaskCloud *pTask)
1446{
1447 LogFlowFuncEnter();
1448 AssertReturnVoid(pTask);
1449
1450 Appliance *pAppliance = pTask->pAppliance;
1451 LogFlowFunc(("Appliance %p taskType=%d\n", pAppliance, pTask->taskType));
1452
1453 switch (pTask->taskType)
1454 {
1455 case TaskCloud::Export:
1456 pAppliance->i_setApplianceState(ApplianceExporting);
1457 pTask->rc = pAppliance->i_exportCloudImpl(pTask);
1458 break;
1459 case TaskCloud::Import:
1460 pAppliance->i_setApplianceState(ApplianceImporting);
1461 pTask->rc = pAppliance->i_importCloudImpl(pTask);
1462 break;
1463 case TaskCloud::ReadData:
1464 pAppliance->i_setApplianceState(ApplianceImporting);
1465 pTask->rc = pAppliance->i_gettingCloudData(pTask);
1466 break;
1467 default:
1468 AssertFailed();
1469 pTask->rc = E_FAIL;
1470 break;
1471 }
1472
1473 pAppliance->i_setApplianceState(ApplianceIdle);
1474
1475 if (!pTask->pProgress.isNull())
1476 pTask->pProgress->i_notifyComplete(pTask->rc);
1477
1478 LogFlowFuncLeave();
1479}
1480
1481/* static */
1482DECLCALLBACK(int) Appliance::TaskCloud::updateProgress(unsigned uPercent, void *pvUser)
1483{
1484 Appliance::TaskCloud* pTask = *(Appliance::TaskCloud**)pvUser;
1485
1486 if ( pTask
1487 && !pTask->pProgress.isNull())
1488 {
1489 BOOL fCanceled;
1490 pTask->pProgress->COMGETTER(Canceled)(&fCanceled);
1491 if (fCanceled)
1492 return -1;
1493 pTask->pProgress->SetCurrentOperationProgress(uPercent);
1494 }
1495 return VINF_SUCCESS;
1496}
1497
1498void i_parseURI(Utf8Str strUri, LocationInfo &locInfo)
1499{
1500 /* Check the URI for the protocol */
1501 if (strUri.startsWith("file://", Utf8Str::CaseInsensitive)) /* File based */
1502 {
1503 locInfo.storageType = VFSType_File;
1504 strUri = strUri.substr(sizeof("file://") - 1);
1505 }
1506 else if (strUri.startsWith("SunCloud://", Utf8Str::CaseInsensitive)) /* Sun Cloud service */
1507 {
1508 locInfo.storageType = VFSType_S3;
1509 strUri = strUri.substr(sizeof("SunCloud://") - 1);
1510 }
1511 else if (strUri.startsWith("S3://", Utf8Str::CaseInsensitive)) /* S3 service */
1512 {
1513 locInfo.storageType = VFSType_S3;
1514 strUri = strUri.substr(sizeof("S3://") - 1);
1515 }
1516 else if (strUri.startsWith("OCI://", Utf8Str::CaseInsensitive)) /* OCI service (storage or compute) */
1517 {
1518 locInfo.storageType = VFSType_Cloud;
1519 locInfo.strProvider = "OCI";
1520 strUri = strUri.substr(sizeof("OCI://") - 1);
1521 }
1522 else if (strUri.startsWith("webdav://", Utf8Str::CaseInsensitive)) /* webdav service */
1523 throw E_NOTIMPL;
1524
1525 /* Not necessary on a file based URI */
1526// if (locInfo.storageType != VFSType_File)
1527// {
1528// size_t uppos = strUri.find("@"); /* username:password combo */
1529// if (uppos != Utf8Str::npos)
1530// {
1531// locInfo.strUsername = strUri.substr(0, uppos);
1532// strUri = strUri.substr(uppos + 1);
1533// size_t upos = locInfo.strUsername.find(":");
1534// if (upos != Utf8Str::npos)
1535// {
1536// locInfo.strPassword = locInfo.strUsername.substr(upos + 1);
1537// locInfo.strUsername = locInfo.strUsername.substr(0, upos);
1538// }
1539// }
1540// size_t hpos = strUri.find("/"); /* hostname part */
1541// if (hpos != Utf8Str::npos)
1542// {
1543// locInfo.strHostname = strUri.substr(0, hpos);
1544// strUri = strUri.substr(hpos);
1545// }
1546// }
1547
1548 locInfo.strPath = strUri;
1549}
1550
1551
1552////////////////////////////////////////////////////////////////////////////////
1553//
1554// IVirtualSystemDescription constructor / destructor
1555//
1556////////////////////////////////////////////////////////////////////////////////
1557
1558/**
1559 * COM initializer.
1560 * @return
1561 */
1562HRESULT VirtualSystemDescription::init()
1563{
1564 /* Enclose the state transition NotReady->InInit->Ready */
1565 AutoInitSpan autoInitSpan(this);
1566 AssertReturn(autoInitSpan.isOk(), E_FAIL);
1567
1568 /* Initialize data */
1569 m = new Data();
1570 m->pConfig = NULL;
1571
1572 /* Confirm a successful initialization */
1573 autoInitSpan.setSucceeded();
1574 return S_OK;
1575}
1576
1577/**
1578* COM uninitializer.
1579*/
1580
1581void VirtualSystemDescription::uninit()
1582{
1583 if (m->pConfig)
1584 delete m->pConfig;
1585 delete m;
1586 m = NULL;
1587}
1588
1589
1590////////////////////////////////////////////////////////////////////////////////
1591//
1592// IVirtualSystemDescription public methods
1593//
1594////////////////////////////////////////////////////////////////////////////////
1595
1596/**
1597 * Public method implementation.
1598 */
1599HRESULT VirtualSystemDescription::getCount(ULONG *aCount)
1600{
1601 if (!aCount)
1602 return E_POINTER;
1603
1604 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1605
1606 *aCount = (ULONG)m->maDescriptions.size();
1607 return S_OK;
1608}
1609
1610/**
1611 * Public method implementation.
1612 */
1613HRESULT VirtualSystemDescription::getDescription(std::vector<VirtualSystemDescriptionType_T> &aTypes,
1614 std::vector<com::Utf8Str> &aRefs,
1615 std::vector<com::Utf8Str> &aOVFValues,
1616 std::vector<com::Utf8Str> &aVBoxValues,
1617 std::vector<com::Utf8Str> &aExtraConfigValues)
1618
1619{
1620 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1621 size_t c = m->maDescriptions.size();
1622 aTypes.resize(c);
1623 aRefs.resize(c);
1624 aOVFValues.resize(c);
1625 aVBoxValues.resize(c);
1626 aExtraConfigValues.resize(c);
1627
1628 for (size_t i = 0; i < c; i++)
1629 {
1630 const VirtualSystemDescriptionEntry &vsde = m->maDescriptions[i];
1631 aTypes[i] = vsde.type;
1632 aRefs[i] = vsde.strRef;
1633 aOVFValues[i] = vsde.strOvf;
1634 aVBoxValues[i] = vsde.strVBoxCurrent;
1635 aExtraConfigValues[i] = vsde.strExtraConfigCurrent;
1636 }
1637 return S_OK;
1638}
1639
1640/**
1641 * Public method implementation.
1642 */
1643HRESULT VirtualSystemDescription::getDescriptionByType(VirtualSystemDescriptionType_T aType,
1644 std::vector<VirtualSystemDescriptionType_T> &aTypes,
1645 std::vector<com::Utf8Str> &aRefs,
1646 std::vector<com::Utf8Str> &aOVFValues,
1647 std::vector<com::Utf8Str> &aVBoxValues,
1648 std::vector<com::Utf8Str> &aExtraConfigValues)
1649{
1650 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1651 std::list<VirtualSystemDescriptionEntry*> vsd = i_findByType(aType);
1652
1653 size_t c = vsd.size();
1654 aTypes.resize(c);
1655 aRefs.resize(c);
1656 aOVFValues.resize(c);
1657 aVBoxValues.resize(c);
1658 aExtraConfigValues.resize(c);
1659
1660 size_t i = 0;
1661 for (list<VirtualSystemDescriptionEntry*>::const_iterator it = vsd.begin(); it != vsd.end(); ++it, ++i)
1662 {
1663 const VirtualSystemDescriptionEntry *vsde = (*it);
1664 aTypes[i] = vsde->type;
1665 aRefs[i] = vsde->strRef;
1666 aOVFValues[i] = vsde->strOvf;
1667 aVBoxValues[i] = vsde->strVBoxCurrent;
1668 aExtraConfigValues[i] = vsde->strExtraConfigCurrent;
1669 }
1670
1671 return S_OK;
1672}
1673
1674/**
1675 * Public method implementation.
1676 */
1677HRESULT VirtualSystemDescription::getValuesByType(VirtualSystemDescriptionType_T aType,
1678 VirtualSystemDescriptionValueType_T aWhich,
1679 std::vector<com::Utf8Str> &aValues)
1680{
1681 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1682
1683 std::list<VirtualSystemDescriptionEntry*> vsd = i_findByType (aType);
1684 aValues.resize((ULONG)vsd.size());
1685
1686 list<VirtualSystemDescriptionEntry*>::const_iterator it;
1687 size_t i = 0;
1688 for (it = vsd.begin();
1689 it != vsd.end();
1690 ++it, ++i)
1691 {
1692 const VirtualSystemDescriptionEntry *vsde = (*it);
1693
1694 Bstr bstr;
1695 switch (aWhich)
1696 {
1697 case VirtualSystemDescriptionValueType_Reference: aValues[i] = vsde->strRef; break;
1698 case VirtualSystemDescriptionValueType_Original: aValues[i] = vsde->strOvf; break;
1699 case VirtualSystemDescriptionValueType_Auto: aValues[i] = vsde->strVBoxCurrent; break;
1700 case VirtualSystemDescriptionValueType_ExtraConfig: aValues[i] = vsde->strExtraConfigCurrent; break;
1701#ifdef VBOX_WITH_XPCOM_CPP_ENUM_HACK
1702 case VirtualSystemDescriptionValueType_32BitHack: AssertFailedBreak(); /* (compiler warnings) */
1703#endif
1704 }
1705 }
1706
1707 return S_OK;
1708}
1709
1710/**
1711 * Public method implementation.
1712 */
1713HRESULT VirtualSystemDescription::setFinalValues(const std::vector<BOOL> &aEnabled,
1714 const std::vector<com::Utf8Str> &aVBoxValues,
1715 const std::vector<com::Utf8Str> &aExtraConfigValues)
1716{
1717#ifndef RT_OS_WINDOWS
1718 // NOREF(aEnabledSize);
1719#endif /* RT_OS_WINDOWS */
1720 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1721
1722 if ( (aEnabled.size() != m->maDescriptions.size())
1723 || (aVBoxValues.size() != m->maDescriptions.size())
1724 || (aExtraConfigValues.size() != m->maDescriptions.size())
1725 )
1726 return E_INVALIDARG;
1727
1728 size_t i = 0;
1729 for (vector<VirtualSystemDescriptionEntry>::iterator it = m->maDescriptions.begin();
1730 it != m->maDescriptions.end();
1731 ++it, ++i)
1732 {
1733 VirtualSystemDescriptionEntry& vsde = *it;
1734
1735 if (aEnabled[i])
1736 {
1737 vsde.strVBoxCurrent = aVBoxValues[i];
1738 vsde.strExtraConfigCurrent = aExtraConfigValues[i];
1739 }
1740 else
1741 vsde.type = VirtualSystemDescriptionType_Ignore;
1742 }
1743
1744 return S_OK;
1745}
1746
1747/**
1748 * Public method implementation.
1749 */
1750HRESULT VirtualSystemDescription::addDescription(VirtualSystemDescriptionType_T aType,
1751 const com::Utf8Str &aVBoxValue,
1752 const com::Utf8Str &aExtraConfigValue)
1753
1754{
1755 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1756 i_addEntry(aType, "", aVBoxValue, aVBoxValue, 0, aExtraConfigValue);
1757 return S_OK;
1758}
1759
1760/**
1761 * Internal method; adds a new description item to the member list.
1762 * @param aType Type of description for the new item.
1763 * @param strRef Reference item; only used with storage controllers.
1764 * @param aOvfValue Corresponding original value from OVF.
1765 * @param aVBoxValue Initial configuration value (can be overridden by caller with setFinalValues).
1766 * @param ulSizeMB Weight for IProgress
1767 * @param strExtraConfig Extra configuration; meaning dependent on type.
1768 */
1769void VirtualSystemDescription::i_addEntry(VirtualSystemDescriptionType_T aType,
1770 const Utf8Str &strRef,
1771 const Utf8Str &aOvfValue,
1772 const Utf8Str &aVBoxValue,
1773 uint32_t ulSizeMB,
1774 const Utf8Str &strExtraConfig /*= ""*/)
1775{
1776 VirtualSystemDescriptionEntry vsde;
1777 vsde.ulIndex = (uint32_t)m->maDescriptions.size(); // each entry gets an index so the client side can reference them
1778 vsde.type = aType;
1779 vsde.strRef = strRef;
1780 vsde.strOvf = aOvfValue;
1781 vsde.strVBoxSuggested /* remember original value */
1782 = vsde.strVBoxCurrent /* and set current value which can be overridden by setFinalValues() */
1783 = aVBoxValue;
1784 vsde.strExtraConfigSuggested
1785 = vsde.strExtraConfigCurrent
1786 = strExtraConfig;
1787 vsde.ulSizeMB = ulSizeMB;
1788
1789 vsde.skipIt = false;
1790
1791 m->maDescriptions.push_back(vsde);
1792}
1793
1794/**
1795 * Private method; returns a list of description items containing all the items from the member
1796 * description items of this virtual system that match the given type.
1797 */
1798std::list<VirtualSystemDescriptionEntry*> VirtualSystemDescription::i_findByType(VirtualSystemDescriptionType_T aType)
1799{
1800 std::list<VirtualSystemDescriptionEntry*> vsd;
1801 for (vector<VirtualSystemDescriptionEntry>::iterator it = m->maDescriptions.begin();
1802 it != m->maDescriptions.end();
1803 ++it)
1804 {
1805 if (it->type == aType)
1806 vsd.push_back(&(*it));
1807 }
1808
1809 return vsd;
1810}
1811
1812HRESULT VirtualSystemDescription::removeDescriptionByType(VirtualSystemDescriptionType_T aType)
1813{
1814 std::vector<VirtualSystemDescriptionEntry>::iterator it = m->maDescriptions.begin();
1815 while (it != m->maDescriptions.end())
1816 {
1817 if (it->type == aType)
1818 it = m->maDescriptions.erase(it);
1819 else
1820 ++it;
1821 }
1822
1823 return S_OK;
1824}
1825
1826/* Private method; delete all records from the list
1827 * m->llDescriptions that match the given type.
1828 */
1829void VirtualSystemDescription::i_removeByType(VirtualSystemDescriptionType_T aType)
1830{
1831 std::vector<VirtualSystemDescriptionEntry>::iterator it = m->maDescriptions.begin();
1832 while (it != m->maDescriptions.end())
1833 {
1834 if (it->type == aType)
1835 it = m->maDescriptions.erase(it);
1836 else
1837 ++it;
1838 }
1839}
1840
1841/**
1842 * Private method; looks thru the member hardware items for the IDE, SATA, or SCSI controller with
1843 * the given reference ID. Useful when needing the controller for a particular
1844 * virtual disk.
1845 */
1846const VirtualSystemDescriptionEntry* VirtualSystemDescription::i_findControllerFromID(const Utf8Str &id)
1847{
1848 vector<VirtualSystemDescriptionEntry>::const_iterator it;
1849 for (it = m->maDescriptions.begin();
1850 it != m->maDescriptions.end();
1851 ++it)
1852 {
1853 const VirtualSystemDescriptionEntry &d = *it;
1854 switch (d.type)
1855 {
1856 case VirtualSystemDescriptionType_HardDiskControllerIDE:
1857 case VirtualSystemDescriptionType_HardDiskControllerSATA:
1858 case VirtualSystemDescriptionType_HardDiskControllerSCSI:
1859 case VirtualSystemDescriptionType_HardDiskControllerVirtioSCSI:
1860 case VirtualSystemDescriptionType_HardDiskControllerSAS:
1861 if (d.strRef == id)
1862 return &d;
1863 break;
1864 default: break; /* Shut up MSC. */
1865 }
1866 }
1867
1868 return NULL;
1869}
1870
1871/**
1872 * Method called from Appliance::Interpret() if the source OVF for a virtual system
1873 * contains a <vbox:Machine> element. This method then attempts to parse that and
1874 * create a MachineConfigFile instance from it which is stored in this instance data
1875 * and can then be used to create a machine.
1876 *
1877 * This must only be called once per instance.
1878 *
1879 * This rethrows all XML and logic errors from MachineConfigFile.
1880 *
1881 * @param elmMachine <vbox:Machine> element with attributes and subelements from some
1882 * DOM tree.
1883 */
1884void VirtualSystemDescription::i_importVBoxMachineXML(const xml::ElementNode &elmMachine)
1885{
1886 settings::MachineConfigFile *pConfig = NULL;
1887
1888 Assert(m->pConfig == NULL);
1889
1890 try
1891 {
1892 pConfig = new settings::MachineConfigFile(NULL);
1893 pConfig->importMachineXML(elmMachine);
1894
1895 m->pConfig = pConfig;
1896 }
1897 catch (...)
1898 {
1899 if (pConfig)
1900 delete pConfig;
1901 throw;
1902 }
1903}
1904
1905/**
1906 * Returns the machine config created by importVBoxMachineXML() or NULL if there's none.
1907 */
1908const settings::MachineConfigFile* VirtualSystemDescription::i_getMachineConfig() const
1909{
1910 return m->pConfig;
1911}
1912
1913/**
1914 * Private method; walks through the array of VirtualSystemDescriptionEntry entries
1915 * and returns the one matching the given index.
1916 */
1917const VirtualSystemDescriptionEntry* VirtualSystemDescription::i_findByIndex(const uint32_t aIndex)
1918{
1919 vector<VirtualSystemDescriptionEntry>::const_iterator it;
1920 for (it = m->maDescriptions.begin();
1921 it != m->maDescriptions.end();
1922 ++it)
1923 {
1924 const VirtualSystemDescriptionEntry &d = *it;
1925 if (d.ulIndex == aIndex)
1926 return &d;
1927 }
1928
1929 return NULL;
1930}
1931
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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