VirtualBox

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

Last change on this file since 23879 was 23879, checked in by vboxsync, 15 years ago

Main: rename snapshot APIs, remove DiscardCurrentSnapshotAndState; tree snapshots implementation still missing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: VBoxManageSnapshot.cpp 23879 2009-10-19 17:26:44Z 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 if (!strcmp(a->argv[1], "take"))
71 {
72 /* there must be a name */
73 if (a->argc < 3)
74 {
75 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
76 rc = E_FAIL;
77 break;
78 }
79 Bstr name(a->argv[2]);
80
81 /* parse the optional arguments */
82 Bstr desc;
83 bool fPause = false;
84 static const RTGETOPTDEF s_aTakeOptions[] =
85 {
86 { "--description", 'd', RTGETOPT_REQ_STRING },
87 { "-description", 'd', RTGETOPT_REQ_STRING },
88 { "-desc", 'd', RTGETOPT_REQ_STRING },
89 { "--pause", 'p', RTGETOPT_REQ_NOTHING }
90 };
91 RTGETOPTSTATE GetOptState;
92 RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTakeOptions, RT_ELEMENTS(s_aTakeOptions), 3, 0 /*fFlags*/);
93 int ch;
94 RTGETOPTUNION Value;
95 while ( SUCCEEDED(rc)
96 && (ch = RTGetOpt(&GetOptState, &Value)))
97 {
98 switch (ch)
99 {
100 case 'p':
101 fPause = true;
102 break;
103
104 case 'd':
105 desc = Value.psz;
106 break;
107
108 default:
109 errorGetOpt(USAGE_SNAPSHOT, ch, &Value);
110 rc = E_FAIL;
111 break;
112 }
113 }
114 if (FAILED(rc))
115 break;
116
117 if (fPause)
118 {
119 MachineState_T machineState;
120 CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
121 if (machineState == MachineState_Running)
122 CHECK_ERROR_BREAK(console, Pause());
123 else
124 fPause = false;
125 }
126
127 ComPtr<IProgress> progress;
128 CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));
129
130 showProgress(progress);
131 LONG iRc;
132 progress->COMGETTER(ResultCode)(&iRc);
133 rc = iRc;
134 if (FAILED(rc))
135 {
136 com::ProgressErrorInfo info(progress);
137 if (info.isBasicAvailable())
138 RTPrintf("Error: failed to take snapshot. Error message: %lS\n", info.getText().raw());
139 else
140 RTPrintf("Error: failed to take snapshot. No error message available!\n");
141 }
142
143 if (fPause)
144 {
145 MachineState_T machineState;
146 CHECK_ERROR_BREAK(console, COMGETTER(State)(&machineState));
147 if (machineState == MachineState_Paused)
148 {
149 if (SUCCEEDED(rc))
150 CHECK_ERROR_BREAK(console, Resume());
151 else
152 console->Resume();
153 }
154 }
155 }
156 else if (!strcmp(a->argv[1], "discard"))
157 {
158 /* exactly one parameter: snapshot name */
159 if (a->argc != 3)
160 {
161 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
162 rc = E_FAIL;
163 break;
164 }
165
166 ComPtr<ISnapshot> snapshot;
167
168 /* assume it's a UUID */
169 Bstr guid(a->argv[2]);
170 if (!guid.isEmpty())
171 {
172 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
173 }
174 else
175 {
176 /* then it must be a name */
177 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
178 }
179
180 snapshot->COMGETTER(Id)(guid.asOutParam());
181
182 ComPtr<IProgress> progress;
183 CHECK_ERROR_BREAK(console, DeleteSnapshot(guid, progress.asOutParam()));
184
185 showProgress(progress);
186 LONG iRc;
187 progress->COMGETTER(ResultCode)(&iRc);
188 rc = iRc;
189 if (FAILED(rc))
190 {
191 com::ProgressErrorInfo info(progress);
192 if (info.isBasicAvailable())
193 RTPrintf("Error: failed to discard snapshot. Error message: %lS\n", info.getText().raw());
194 else
195 RTPrintf("Error: failed to discard snapshot. No error message available!\n");
196 }
197 }
198 else if (!strcmp(a->argv[1], "discardcurrent"))
199 {
200 if ( (a->argc != 3)
201 || ( strcmp(a->argv[2], "--state")
202 && strcmp(a->argv[2], "-state")))
203 {
204 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[2]).raw());
205 rc = E_FAIL;
206 break;
207 }
208
209 ComPtr<ISnapshot> pCurrentSnapshot;
210 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(pCurrentSnapshot.asOutParam()));
211
212 ComPtr<IProgress> pProgress;
213 CHECK_ERROR_BREAK(console, RestoreSnapshot(pCurrentSnapshot, pProgress.asOutParam()));
214
215 showProgress(pProgress);
216 LONG iRc;
217 pProgress->COMGETTER(ResultCode)(&iRc);
218 rc = iRc;
219 if (FAILED(rc))
220 {
221 com::ProgressErrorInfo info(pProgress);
222 if (info.isBasicAvailable())
223 RTPrintf("Error: failed to restore snapshot. Error message: %lS\n", info.getText().raw());
224 else
225 RTPrintf("Error: failed to restore snapshot. No error message available!\n");
226 }
227
228 }
229 else if (!strcmp(a->argv[1], "edit"))
230 {
231 if (a->argc < 3)
232 {
233 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
234 rc = E_FAIL;
235 break;
236 }
237
238 ComPtr<ISnapshot> snapshot;
239
240 if ( !strcmp(a->argv[2], "--current")
241 || !strcmp(a->argv[2], "-current"))
242 {
243 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
244 }
245 else
246 {
247 /* assume it's a UUID */
248 Bstr guid(a->argv[2]);
249 if (!guid.isEmpty())
250 {
251 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
252 }
253 else
254 {
255 /* then it must be a name */
256 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
257 }
258 }
259
260 /* parse options */
261 for (int i = 3; i < a->argc; i++)
262 {
263 if ( !strcmp(a->argv[i], "--name")
264 || !strcmp(a->argv[i], "-name")
265 || !strcmp(a->argv[i], "-newname"))
266 {
267 if (a->argc <= i + 1)
268 {
269 errorArgument("Missing argument to '%s'", a->argv[i]);
270 rc = E_FAIL;
271 break;
272 }
273 i++;
274 snapshot->COMSETTER(Name)(Bstr(a->argv[i]));
275 }
276 else if ( !strcmp(a->argv[i], "--description")
277 || !strcmp(a->argv[i], "-description")
278 || !strcmp(a->argv[i], "-newdesc"))
279 {
280 if (a->argc <= i + 1)
281 {
282 errorArgument("Missing argument to '%s'", a->argv[i]);
283 rc = E_FAIL;
284 break;
285 }
286 i++;
287 snapshot->COMSETTER(Description)(Bstr(a->argv[i]));
288 }
289 else
290 {
291 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
292 rc = E_FAIL;
293 break;
294 }
295 }
296
297 }
298 else if (!strcmp(a->argv[1], "showvminfo"))
299 {
300 /* exactly one parameter: snapshot name */
301 if (a->argc != 3)
302 {
303 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
304 rc = E_FAIL;
305 break;
306 }
307
308 ComPtr<ISnapshot> snapshot;
309
310 /* assume it's a UUID */
311 Bstr guid(a->argv[2]);
312 if (!guid.isEmpty())
313 {
314 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
315 }
316 else
317 {
318 /* then it must be a name */
319 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
320 }
321
322 /* get the machine of the given snapshot */
323 ComPtr<IMachine> machine;
324 snapshot->COMGETTER(Machine)(machine.asOutParam());
325 showVMInfo(a->virtualBox, machine, VMINFO_NONE, console);
326 }
327 else
328 {
329 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
330 rc = E_FAIL;
331 }
332 } while (0);
333
334 a->session->Close();
335
336 return SUCCEEDED(rc) ? 0 : 1;
337}
338
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