2 * suspend.c: Demo program showing how to suspend a domain
4 * Copyright (C) 2006-2013 Red Hat, Inc.
5 * Copyright (C) 2006 Daniel P. Berrange
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
24 #include <libvirt/libvirt.h>
25 #include <libvirt/virterror.h>
33 /* On mingw, there's a header file that poisons the well:
37 *domtop.c:40:0: warning: "ERROR" redefined [enabled by default]
38 * #define ERROR(...) \
40 *In file included from /usr/i686-w64-mingw32/sys-root/mingw/include/windows.h:71:0,
41 * from /usr/i686-w64-mingw32/sys-root/mingw/include/winsock2.h:23,
42 * from ../../gnulib/lib/unistd.h:48,
44 * /usr/i686-w64-mingw32/sys-root/mingw/include/wingdi.h:75:0: note: this is the location of the previous definition
50 fprintf(stderr, "ERROR %s:%d : ", __FUNCTION__, __LINE__); \
51 fprintf(stderr, __VA_ARGS__); \
52 fprintf(stderr, "\n"); \
59 fprintf(stderr, "DEBUG %s:%d : ", __FUNCTION__, __LINE__); \
60 fprintf(stderr, __VA_ARGS__); \
61 fprintf(stderr, "\n"); \
65 print_usage(const char *progname
)
67 const char *unified_progname
;
69 if (!(unified_progname
= strrchr(progname
, '/')))
70 unified_progname
= progname
;
74 printf("\n%s [options] [domain name]\n\n"
76 " -d | --debug enable debug printings\n"
77 " -h | --help print this help\n"
78 " -c | --connect=URI hypervisor connection URI\n"
79 " -s | --seconds=X suspend domain for X seconds (default 1)\n",
84 parse_argv(int argc
, char *argv
[],
86 const char **dom_name
,
87 unsigned int *seconds
)
93 struct option opt
[] = {
94 {"debug", no_argument
, NULL
, 'd'},
95 {"help", no_argument
, NULL
, 'h'},
96 {"connect", required_argument
, NULL
, 'c'},
97 {"seconds", required_argument
, NULL
, 's'},
101 while ((arg
= getopt_long(argc
, argv
, "+:dhc:s:", opt
, NULL
)) != -1) {
107 print_usage(argv
[0]);
114 /* strtoul man page suggest clearing errno prior to call */
116 val
= strtoul(optarg
, &p
, 10);
117 if (errno
|| *p
|| p
== optarg
) {
118 ERROR("Invalid number: '%s'", optarg
);
122 if (*seconds
!= val
) {
123 ERROR("Integer overflow: %ld", val
);
128 ERROR("option '-%c' requires an argument", optopt
);
132 ERROR("unsupported option '-%c'. See --help.", optopt
);
134 ERROR("unsupported option '%s'. See --help.", argv
[optind
- 1]);
137 ERROR("unknown option");
143 *dom_name
= argv
[optind
];
151 fetch_domains(virConnectPtr conn
)
153 int num_domains
, ret
= -1;
154 virDomainPtr
*domains
= NULL
;
156 const int list_flags
= VIR_CONNECT_LIST_DOMAINS_ACTIVE
;
158 DEBUG("Fetching list of running domains");
159 num_domains
= virConnectListAllDomains(conn
, &domains
, list_flags
);
161 DEBUG("num_domains=%d", num_domains
);
162 if (num_domains
< 0) {
163 ERROR("Unable to fetch list of running domains");
167 printf("Running domains:\n");
168 printf("----------------\n");
169 for (i
= 0; i
< num_domains
; i
++) {
170 virDomainPtr dom
= domains
[i
];
171 const char *dom_name
= virDomainGetName(dom
);
172 printf("%s\n", dom_name
);
183 suspend_and_resume(virConnectPtr conn
,
184 const char *dom_name
,
185 unsigned int seconds
)
189 virDomainInfo dom_info
;
191 if (!(dom
= virDomainLookupByName(conn
, dom_name
))) {
192 ERROR("Unable to find domain '%s'", dom_name
);
196 if (virDomainGetInfo(dom
, &dom_info
) < 0) {
197 ERROR("Unable to get domain info");
201 DEBUG("Domain state %d", dom_info
.state
);
203 switch (dom_info
.state
) {
204 case VIR_DOMAIN_NOSTATE
:
205 case VIR_DOMAIN_RUNNING
:
206 case VIR_DOMAIN_BLOCKED
:
207 /* In these states the domain can be suspended */
208 DEBUG("Suspending domain");
209 if (virDomainSuspend(dom
) < 0) {
210 ERROR("Unable to suspend domain");
214 DEBUG("Domain suspended. Entering sleep for %u seconds.", seconds
);
216 DEBUG("Sleeping done. Resuming the domain.");
218 if (virDomainResume(dom
) < 0) {
219 ERROR("Unable to resume domain");
225 /* In all other states domain can't be suspended */
226 ERROR("Domain is not in a state where it can be suspended: %d",
239 main(int argc
, char *argv
[])
241 int ret
= EXIT_FAILURE
;
242 virConnectPtr conn
= NULL
;
243 const char *uri
= NULL
;
244 const char *dom_name
= NULL
;
245 unsigned int seconds
= 1; /* Suspend domain for this long */
246 const int connect_flags
= 0; /* No connect flags for now */
248 if (parse_argv(argc
, argv
, &uri
, &dom_name
, &seconds
) < 0)
251 DEBUG("Proceeding with uri=%s dom_name=%s seconds=%u",
252 uri
, dom_name
, seconds
);
254 if (!(conn
= virConnectOpenAuth(uri
,
255 virConnectAuthPtrDefault
,
257 ERROR("Failed to connect to hypervisor");
261 DEBUG("Successfully connected");
264 if (fetch_domains(conn
) == 0)
269 if (suspend_and_resume(conn
, dom_name
, seconds
) < 0)
276 tmp
= virConnectClose(conn
);
278 ERROR("Failed to disconnect from the hypervisor");
280 } else if (tmp
> 0) {
281 ERROR("One or more references were leaked after "
282 "disconnect from the hypervisor");
285 DEBUG("Connection successfully closed");