VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp@ 24002

Last change on this file since 24002 was 23882, checked in by vboxsync, 16 years ago

Main: make restoreSnapshot() work better, adjust VBoxManage

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: VBoxManageSnapshot.cpp 23882 2009-10-19 18:36:03Z vboxsync $ */
2/** @file
3 * VBoxManage - The 'snapshot' command.
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#include <VBox/com/com.h>
26#include <VBox/com/string.h>
27#include <VBox/com/ErrorInfo.h>
28#include <VBox/com/errorprint.h>
29
30#include <VBox/com/VirtualBox.h>
31
32#include <iprt/stream.h>
33#include <iprt/getopt.h>
34
35#include "VBoxManage.h"
36using namespace com;
37
38int handleSnapshot(HandlerArg *a)
39{
40 HRESULT rc;
41
42 /* we need at least a VM and a command */
43 if (a->argc < 2)
44 return errorSyntax(USAGE_SNAPSHOT, "Not enough parameters");
45
46 /* the first argument must be the VM */
47 ComPtr<IMachine> machine;
48 /* assume it's a UUID */
49 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
50 if (FAILED(rc) || !machine)
51 {
52 /* must be a name */
53 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
54 }
55 if (!machine)
56 return 1;
57 Bstr guid;
58 machine->COMGETTER(Id)(guid.asOutParam());
59
60 do
61 {
62 /* we have to open a session for this task. First try an existing session */
63 rc = a->virtualBox->OpenExistingSession(a->session, guid);
64 if (FAILED(rc))
65 CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
66 ComPtr<IConsole> console;
67 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
68
69 /* switch based on the command */
70 bool fDelete = false, fRestore = false;
71 if (!strcmp(a->argv[1], "take"))
72 {
73 /* there must be a name */
74 if (a->argc < 3)
75 {
76 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
77 rc = E_FAIL;
78 break;
79 }
80 Bstr name(a->argv[2]);
81
82 /* parse the optional arguments */
83 Bstr desc;
84 bool fPause = false;
85 static const RTGETOPTDEF s_aTakeOptions[] =
86 {
87 { "--description", 'd', RTGETOPT_REQ_STRING },
88 { "-description", 'd', RTGETOPT_REQ_STRING },
89 { "-desc", 'd', RTGETOPT_REQ_STRING },
90 { "--pause", 'p', RTGETOPT_REQ_NOTHING }
91 };
92 RTGETOPTSTATE GetOptState;
93 RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTakeOptions, RT_ELEMENTS(s_aTakeOptions), 3, 0 /*fFlags*/);
94 int ch;
95 RTGETOPTUNION Value;
96 while ( SUCCEEDED(rc)
97 && (ch = RTGetOpt(&GetOptState, &Value)))
98 {
99 switch (ch)
100 {
101 case 'p':
102 fPause = true;
103 break;
104
105 case 'd':
106 desc = Value.psz;
107 break;
108
109 default:
110 errorGetOpt(USAGE_SNAPSHOT, ch, &Value);
111 rc = E_FAIL;
112 break;
113 }
114 }
115 if (FAILED(rc))
116 break;
117
118 if (fPause)
119 {
120 MachineState_T machineState;
121 CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
122 if (machineState == MachineState_Running)
123 CHECK_ERROR_BREAK(console, Pause());
124 else
125 fPause = false;
126 }
127
128 ComPtr<IProgress> progress;
129 CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));
130
131 showProgress(progress);
132 LONG iRc;
133 progress->COMGETTER(ResultCode)(&iRc);
134 rc = iRc;
135 if (FAILED(rc))
136 {
137 com::ProgressErrorInfo info(progress);
138 if (info.isBasicAvailable())
139 RTPrintf("Error: failed to take snapshot. Error message: %lS\n", info.getText().raw());
140 else
141 RTPrintf("Error: failed to take snapshot. No error message available!\n");
142 }
143
144 if (fPause)
145 {
146 MachineState_T machineState;
147 CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
148 if (machineState == MachineState_Paused)
149 {
150 if (SUCCEEDED(rc))
151 CHECK_ERROR_BREAK(console, Resume());
152 else
153 console->Resume();
154 }
155 }
156 }
157 else if ( (fDelete = !strcmp(a->argv[1], "delete"))
158 || (fRestore = !strcmp(a->argv[1], "restore"))
159 )
160 {
161 /* exactly one parameter: snapshot name */
162 if (a->argc != 3)
163 {
164 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
165 rc = E_FAIL;
166 break;
167 }
168
169 ComPtr<ISnapshot> pSnapshot;
170
171 /* assume it's a UUID */
172 Bstr guid(a->argv[2]);
173 if (!guid.isEmpty())
174 {
175 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, pSnapshot.asOutParam()));
176 }
177 else
178 {
179 /* then it must be a name */
180 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), pSnapshot.asOutParam()));
181 pSnapshot->COMGETTER(Id)(guid.asOutParam());
182 }
183
184 ComPtr<IProgress> pProgress;
185 if (fDelete)
186 {
187 CHECK_ERROR_BREAK(console, DeleteSnapshot(guid, pProgress.asOutParam()));
188 }
189 else
190 {
191 // must be restore
192 CHECK_ERROR_BREAK(console, RestoreSnapshot(pSnapshot, pProgress.asOutParam()));
193 }
194
195 showProgress(pProgress);
196 LONG iRc;
197 pProgress->COMGETTER(ResultCode)(&iRc);
198 rc = iRc;
199 if (FAILED(rc))
200 {
201 com::ProgressErrorInfo info(pProgress);
202 if (info.isBasicAvailable())
203 RTPrintf("Error: snapshot operation failed. Error message: %lS\n", info.getText().raw());
204 else
205 RTPrintf("Error: snapshot operation failed. No error message available!\n");
206 }
207 }
208 else if (!strcmp(a->argv[1], "edit"))
209 {
210 if (a->argc < 3)
211 {
212 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
213 rc = E_FAIL;
214 break;
215 }
216
217 ComPtr<ISnapshot> snapshot;
218
219 if ( !strcmp(a->argv[2], "--current")
220 || !strcmp(a->argv[2], "-current"))
221 {
222 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
223 }
224 else
225 {
226 /* assume it's a UUID */
227 Bstr guid(a->argv[2]);
228 if (!guid.isEmpty())
229 {
230 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
231 }
232 else
233 {
234 /* then it must be a name */
235 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
236 }
237 }
238
239 /* parse options */
240 for (int i = 3; i < a->argc; i++)
241 {
242 if ( !strcmp(a->argv[i], "--name")
243 || !strcmp(a->argv[i], "-name")
244 || !strcmp(a->argv[i], "-newname"))
245 {
246 if (a->argc <= i + 1)
247 {
248 errorArgument("Missing argument to '%s'", a->argv[i]);
249 rc = E_FAIL;
250 break;
251 }
252 i++;
253 snapshot->COMSETTER(Name)(Bstr(a->argv[i]));
254 }
255 else if ( !strcmp(a->argv[i], "--description")
256 || !strcmp(a->argv[i], "-description")
257 || !strcmp(a->argv[i], "-newdesc"))
258 {
259 if (a->argc <= i + 1)
260 {
261 errorArgument("Missing argument to '%s'", a->argv[i]);
262 rc = E_FAIL;
263 break;
264 }
265 i++;
266 snapshot->COMSETTER(Description)(Bstr(a->argv[i]));
267 }
268 else
269 {
270 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
271 rc = E_FAIL;
272 break;
273 }
274 }
275
276 }
277 else if (!strcmp(a->argv[1], "showvminfo"))
278 {
279 /* exactly one parameter: snapshot name */
280 if (a->argc != 3)
281 {
282 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
283 rc = E_FAIL;
284 break;
285 }
286
287 ComPtr<ISnapshot> snapshot;
288
289 /* assume it's a UUID */
290 Bstr guid(a->argv[2]);
291 if (!guid.isEmpty())
292 {
293 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
294 }
295 else
296 {
297 /* then it must be a name */
298 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
299 }
300
301 /* get the machine of the given snapshot */
302 ComPtr<IMachine> machine;
303 snapshot->COMGETTER(Machine)(machine.asOutParam());
304 showVMInfo(a->virtualBox, machine, VMINFO_NONE, console);
305 }
306 else
307 {
308 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
309 rc = E_FAIL;
310 }
311 } while (0);
312
313 a->session->Close();
314
315 return SUCCEEDED(rc) ? 0 : 1;
316}
317
Note: See TracBrowser for help on using the repository browser.

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