VirtualBox

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

Last change on this file since 107438 was 107248, checked in by vboxsync, 6 weeks ago

VBox/ostypes.h+Main/{Global,Appliance}+VMMDev+FE/Qt: Fill in some
missing ARM64 pieces from some recent incomplete updates to
Global::OSTypes[] such as the appliance import g_aOsTypes[] array and
the icon matching code in the GUI. Also add a few new Linux ARM entries
such as 'Red Hat 9.x' and 'Ubuntu 24.10'.

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

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