VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/wizards/exportappliance/UIWizardExportApp.cpp@ 103551

Last change on this file since 103551 was 103549, checked in by vboxsync, 9 months ago

FE/Qt: UIVirtualBoxManager & UINotificationObjects: Get rid of UICommon include in the header.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: UIWizardExportApp.cpp 103549 2024-02-23 15:42:38Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIWizardExportApp class implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2023 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/* Qt includes: */
29#include <QFileInfo>
30#include <QPushButton>
31#include <QVariant>
32
33/* GUI includes: */
34#include "UIAddDiskEncryptionPasswordDialog.h"
35#include "UICommon.h"
36#include "UIMessageCenter.h"
37#include "UIModalWindowManager.h"
38#include "UINotificationCenter.h"
39#include "UIWizardExportApp.h"
40#include "UIWizardExportAppPageExpert.h"
41#include "UIWizardExportAppPageFormat.h"
42#include "UIWizardExportAppPageSettings.h"
43#include "UIWizardExportAppPageVMs.h"
44
45/* COM includes: */
46#include "CAppliance.h"
47#include "CVFSExplorer.h"
48
49
50UIWizardExportApp::UIWizardExportApp(QWidget *pParent,
51 const QStringList &predefinedMachineNames /* = QStringList() */,
52 bool fFastTraverToExportOCI /* = false */)
53 : UINativeWizard(pParent, WizardType_ExportAppliance, WizardMode_Auto,
54 fFastTraverToExportOCI ? "cloud-export-oci" : "ovf")
55 , m_predefinedMachineNames(predefinedMachineNames)
56 , m_fFastTraverToExportOCI(fFastTraverToExportOCI)
57 , m_fFormatCloudOne(false)
58 , m_enmMACAddressExportPolicy(MACAddressExportPolicy_KeepAllMACs)
59 , m_fManifestSelected(false)
60 , m_fIncludeISOsSelected(false)
61 , m_enmCloudExportMode(CloudExportMode_DoNotAsk)
62{
63#ifndef VBOX_WS_MAC
64 /* Assign watermark: */
65 setPixmapName(":/wizard_ovf_export.png");
66#else
67 /* Assign background image: */
68 setPixmapName(":/wizard_ovf_export_bg.png");
69#endif
70}
71
72void UIWizardExportApp::goForward()
73{
74 wizardButton(WizardButtonType_Next)->click();
75}
76
77void UIWizardExportApp::disableButtons()
78{
79 wizardButton(WizardButtonType_Expert)->setEnabled(false);
80 wizardButton(WizardButtonType_Back)->setEnabled(false);
81 wizardButton(WizardButtonType_Next)->setEnabled(false);
82}
83
84QString UIWizardExportApp::uri(bool fWithFile) const
85{
86 /* For Cloud formats: */
87 if (isFormatCloudOne())
88 return QString("%1://").arg(format());
89 else
90 {
91 /* Prepare storage path: */
92 QString strPath = path();
93 /* Append file name if requested: */
94 if (!fWithFile)
95 {
96 QFileInfo fi(strPath);
97 strPath = fi.path();
98 }
99
100 /* Just path by default: */
101 return strPath;
102 }
103}
104
105bool UIWizardExportApp::exportAppliance()
106{
107 /* Check whether there was cloud target selected: */
108 if (isFormatCloudOne())
109 {
110 /* Get appliance: */
111 CAppliance comAppliance = cloudAppliance();
112 AssertReturn(comAppliance.isNotNull(), false);
113
114 /* Export the VMs, on success we are finished: */
115 return exportVMs(comAppliance);
116 }
117 else
118 {
119 /* Get appliance: */
120 CAppliance comAppliance = localAppliance();
121 AssertReturn(comAppliance.isNotNull(), false);
122
123 /* We need to know every filename which will be created, so that we can ask the user for confirmation of overwriting.
124 * For that we iterating over all virtual systems & fetch all descriptions of the type HardDiskImage. Also add the
125 * manifest file to the check. In the .ova case only the target file itself get checked. */
126
127 /* Compose a list of all required files: */
128 QFileInfo fi(path());
129 QVector<QString> files;
130
131 /* Add arhive itself: */
132 files << fi.fileName();
133
134 /* If archive is of .ovf type: */
135 if (fi.suffix().toLower() == "ovf")
136 {
137 /* Add manifest file if requested: */
138 if (isManifestSelected())
139 files << fi.baseName() + ".mf";
140
141 /* Add all hard disk images: */
142 CVirtualSystemDescriptionVector vsds = comAppliance.GetVirtualSystemDescriptions();
143 for (int i = 0; i < vsds.size(); ++i)
144 {
145 QVector<KVirtualSystemDescriptionType> types;
146 QVector<QString> refs, origValues, configValues, extraConfigValues;
147 vsds[i].GetDescriptionByType(KVirtualSystemDescriptionType_HardDiskImage, types,
148 refs, origValues, configValues, extraConfigValues);
149 foreach (const QString &strValue, origValues)
150 files << QString("%2").arg(strValue);
151 }
152 }
153
154 /* Initialize VFS explorer: */
155 CVFSExplorer comExplorer = comAppliance.CreateVFSExplorer(uri(false /* fWithFile */));
156 if (!comAppliance.isOk())
157 {
158 UINotificationMessage::cannotCreateVfsExplorer(comAppliance, notificationCenter());
159 return false;
160 }
161
162 /* Update VFS explorer: */
163 UINotificationProgressVFSExplorerUpdate *pNotification =
164 new UINotificationProgressVFSExplorerUpdate(comExplorer);
165 if (!handleNotificationProgressNow(pNotification))
166 return false;
167
168 /* Confirm overwriting for existing files: */
169 QVector<QString> exists = comExplorer.Exists(files);
170 if (!msgCenter().confirmOverridingFiles(exists, this))
171 return false;
172
173 /* DELETE all the files which exists after everything is confirmed: */
174 if (!exists.isEmpty())
175 {
176 /* Remove files with VFS explorer: */
177 UINotificationProgressVFSExplorerFilesRemove *pNotification =
178 new UINotificationProgressVFSExplorerFilesRemove(comExplorer, exists);
179 if (!handleNotificationProgressNow(pNotification))
180 return false;
181 }
182
183 /* Export the VMs, on success we are finished: */
184 return exportVMs(comAppliance);
185 }
186}
187
188void UIWizardExportApp::createVsdLaunchForm()
189{
190 /* Acquire prepared client and description: */
191 CCloudClient comClient = cloudClient();
192 CVirtualSystemDescription comVSD = vsd();
193 AssertReturnVoid(comClient.isNotNull() && comVSD.isNotNull());
194
195 /* Create launch VSD form: */
196 UINotificationProgressLaunchVSDFormCreate *pNotification = new UINotificationProgressLaunchVSDFormCreate(comClient,
197 comVSD,
198 format(),
199 profileName());
200 connect(pNotification, &UINotificationProgressLaunchVSDFormCreate::sigVSDFormCreated,
201 this, &UIWizardExportApp::setVsdLaunchForm);
202 handleNotificationProgressNow(pNotification);
203}
204
205bool UIWizardExportApp::createCloudVM()
206{
207 /* Acquire prepared client and description: */
208 CCloudClient comClient = cloudClient();
209 CVirtualSystemDescription comVSD = vsd();
210 AssertReturn(comClient.isNotNull() && comVSD.isNotNull(), false);
211
212 /* Initiate cloud VM creation procedure: */
213 CCloudMachine comMachine;
214
215 /* Create cloud VM: */
216 UINotificationProgressCloudMachineCreate *pNotification = new UINotificationProgressCloudMachineCreate(comClient,
217 comMachine,
218 comVSD,
219 format(),
220 profileName());
221 connect(pNotification, &UINotificationProgressCloudMachineCreate::sigCloudMachineCreated,
222 &uiCommon(), &UICommon::sltHandleCloudMachineAdded);
223 gpNotificationCenter->append(pNotification);
224
225 /* Return result: */
226 return true;
227}
228
229void UIWizardExportApp::populatePages()
230{
231 /* Create corresponding pages: */
232 switch (mode())
233 {
234 case WizardMode_Basic:
235 {
236 addPage(new UIWizardExportAppPageVMs(m_predefinedMachineNames, m_fFastTraverToExportOCI));
237 addPage(new UIWizardExportAppPageFormat(m_fFastTraverToExportOCI));
238 addPage(new UIWizardExportAppPageSettings);
239 break;
240 }
241 case WizardMode_Expert:
242 {
243 addPage(new UIWizardExportAppPageExpert(m_predefinedMachineNames, m_fFastTraverToExportOCI));
244 break;
245 }
246 default:
247 {
248 AssertMsgFailed(("Invalid mode: %d", mode()));
249 break;
250 }
251 }
252}
253
254void UIWizardExportApp::retranslateUi()
255{
256 /* Call to base-class: */
257 UINativeWizard::retranslateUi();
258
259 /* Translate wizard: */
260 setWindowTitle(tr("Export Virtual Appliance"));
261 /// @todo implement this?
262 //setButtonText(QWizard::FinishButton, tr("Export"));
263}
264
265bool UIWizardExportApp::exportVMs(CAppliance &comAppliance)
266{
267 /* Get the map of the password IDs: */
268 EncryptedMediumMap encryptedMedia;
269 foreach (const QString &strPasswordId, comAppliance.GetPasswordIds())
270 foreach (const QUuid &uMediumId, comAppliance.GetMediumIdsForPasswordId(strPasswordId))
271 encryptedMedia.insert(strPasswordId, uMediumId);
272
273 /* Ask for the disk encryption passwords if necessary: */
274 if (!encryptedMedia.isEmpty())
275 {
276 /* Modal dialog can be destroyed in own event-loop as a part of application
277 * termination procedure. We have to make sure that the dialog pointer is
278 * always up to date. So we are wrapping created dialog with QPointer. */
279 QPointer<UIAddDiskEncryptionPasswordDialog> pDlg =
280 new UIAddDiskEncryptionPasswordDialog(this,
281 window()->windowTitle(),
282 encryptedMedia);
283
284 /* Execute the dialog: */
285 if (pDlg->exec() != QDialog::Accepted)
286 {
287 /* Delete the dialog: */
288 delete pDlg;
289 return false;
290 }
291
292 /* Acquire the passwords provided: */
293 const EncryptionPasswordMap encryptionPasswords = pDlg->encryptionPasswords();
294
295 /* Delete the dialog: */
296 delete pDlg;
297
298 /* Provide appliance with passwords if possible: */
299 comAppliance.AddPasswords(encryptionPasswords.keys().toVector(),
300 encryptionPasswords.values().toVector());
301 if (!comAppliance.isOk())
302 {
303 UINotificationMessage::cannotAddDiskEncryptionPassword(comAppliance, notificationCenter());
304 return false;
305 }
306 }
307
308 /* Prepare export options: */
309 QVector<KExportOptions> options;
310 switch (macAddressExportPolicy())
311 {
312 case MACAddressExportPolicy_StripAllNonNATMACs: options.append(KExportOptions_StripAllNonNATMACs); break;
313 case MACAddressExportPolicy_StripAllMACs: options.append(KExportOptions_StripAllMACs); break;
314 default: break;
315 }
316 if (isManifestSelected())
317 options.append(KExportOptions_CreateManifest);
318 if (isIncludeISOsSelected())
319 options.append(KExportOptions_ExportDVDImages);
320
321 /* Is this VM being exported to cloud? */
322 if (isFormatCloudOne())
323 {
324 /* Export appliance: */
325 UINotificationProgressApplianceWrite *pNotification = new UINotificationProgressApplianceWrite(comAppliance,
326 format(),
327 options,
328 uri());
329 if (cloudExportMode() == CloudExportMode_DoNotAsk)
330 gpNotificationCenter->append(pNotification);
331 else
332 handleNotificationProgressNow(pNotification);
333 }
334 /* Is this VM being exported locally? */
335 else
336 {
337 /* Export appliance: */
338 UINotificationProgressApplianceWrite *pNotification = new UINotificationProgressApplianceWrite(comAppliance,
339 format(),
340 options,
341 uri());
342 gpNotificationCenter->append(pNotification);
343 }
344
345 /* Success finally: */
346 return true;
347}
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