examples: Organize C examples into categories
[libvirt/ericb.git] / examples / domain / suspend.c
blobaf61129ecc7882c1e32d04341aabf0b7987264bd
1 /*
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/>.
22 #include <errno.h>
23 #include <getopt.h>
24 #include <libvirt/libvirt.h>
25 #include <libvirt/virterror.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
31 static int debug;
33 /* On mingw, there's a header file that poisons the well:
36 * CC domtop.o
37 *domtop.c:40:0: warning: "ERROR" redefined [enabled by default]
38 * #define ERROR(...) \
39 * ^
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,
43 * from domtop.c:35:
44 * /usr/i686-w64-mingw32/sys-root/mingw/include/wingdi.h:75:0: note: this is the location of the previous definition
45 * #define ERROR 0
47 #undef ERROR
48 #define ERROR(...) \
49 do { \
50 fprintf(stderr, "ERROR %s:%d : ", __FUNCTION__, __LINE__); \
51 fprintf(stderr, __VA_ARGS__); \
52 fprintf(stderr, "\n"); \
53 } while (0)
55 #define DEBUG(...) \
56 do { \
57 if (!debug) \
58 break; \
59 fprintf(stderr, "DEBUG %s:%d : ", __FUNCTION__, __LINE__); \
60 fprintf(stderr, __VA_ARGS__); \
61 fprintf(stderr, "\n"); \
62 } while (0)
64 static void
65 print_usage(const char *progname)
67 const char *unified_progname;
69 if (!(unified_progname = strrchr(progname, '/')))
70 unified_progname = progname;
71 else
72 unified_progname++;
74 printf("\n%s [options] [domain name]\n\n"
75 " options:\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",
80 unified_progname);
83 static int
84 parse_argv(int argc, char *argv[],
85 const char **uri,
86 const char **dom_name,
87 unsigned int *seconds)
89 int ret = -1;
90 int arg;
91 unsigned long val;
92 char *p;
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'},
98 {NULL, 0, NULL, 0}
101 while ((arg = getopt_long(argc, argv, "+:dhc:s:", opt, NULL)) != -1) {
102 switch (arg) {
103 case 'd':
104 debug = 1;
105 break;
106 case 'h':
107 print_usage(argv[0]);
108 exit(EXIT_SUCCESS);
109 break;
110 case 'c':
111 *uri = optarg;
112 break;
113 case 's':
114 /* strtoul man page suggest clearing errno prior to call */
115 errno = 0;
116 val = strtoul(optarg, &p, 10);
117 if (errno || *p || p == optarg) {
118 ERROR("Invalid number: '%s'", optarg);
119 goto cleanup;
121 *seconds = val;
122 if (*seconds != val) {
123 ERROR("Integer overflow: %ld", val);
124 goto cleanup;
126 break;
127 case ':':
128 ERROR("option '-%c' requires an argument", optopt);
129 exit(EXIT_FAILURE);
130 case '?':
131 if (optopt)
132 ERROR("unsupported option '-%c'. See --help.", optopt);
133 else
134 ERROR("unsupported option '%s'. See --help.", argv[optind - 1]);
135 exit(EXIT_FAILURE);
136 default:
137 ERROR("unknown option");
138 exit(EXIT_FAILURE);
142 if (argc > optind)
143 *dom_name = argv[optind];
145 ret = 0;
146 cleanup:
147 return ret;
150 static int
151 fetch_domains(virConnectPtr conn)
153 int num_domains, ret = -1;
154 virDomainPtr *domains = NULL;
155 ssize_t i;
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");
164 goto cleanup;
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);
173 virDomainFree(dom);
176 ret = 0;
177 cleanup:
178 free(domains);
179 return ret;
182 static int
183 suspend_and_resume(virConnectPtr conn,
184 const char *dom_name,
185 unsigned int seconds)
187 int ret = -1;
188 virDomainPtr dom;
189 virDomainInfo dom_info;
191 if (!(dom = virDomainLookupByName(conn, dom_name))) {
192 ERROR("Unable to find domain '%s'", dom_name);
193 goto cleanup;
196 if (virDomainGetInfo(dom, &dom_info) < 0) {
197 ERROR("Unable to get domain info");
198 goto cleanup;
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");
211 goto cleanup;
214 DEBUG("Domain suspended. Entering sleep for %u seconds.", seconds);
215 sleep(seconds);
216 DEBUG("Sleeping done. Resuming the domain.");
218 if (virDomainResume(dom) < 0) {
219 ERROR("Unable to resume domain");
220 goto cleanup;
222 break;
224 default:
225 /* In all other states domain can't be suspended */
226 ERROR("Domain is not in a state where it can be suspended: %d",
227 dom_info.state);
228 goto cleanup;
231 ret = 0;
232 cleanup:
233 if (dom)
234 virDomainFree(dom);
235 return ret;
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)
249 goto cleanup;
251 DEBUG("Proceeding with uri=%s dom_name=%s seconds=%u",
252 uri, dom_name, seconds);
254 if (!(conn = virConnectOpenAuth(uri,
255 virConnectAuthPtrDefault,
256 connect_flags))) {
257 ERROR("Failed to connect to hypervisor");
258 goto cleanup;
261 DEBUG("Successfully connected");
263 if (!dom_name) {
264 if (fetch_domains(conn) == 0)
265 ret = EXIT_SUCCESS;
266 goto cleanup;
269 if (suspend_and_resume(conn, dom_name, seconds) < 0)
270 goto cleanup;
272 ret = EXIT_SUCCESS;
273 cleanup:
274 if (conn) {
275 int tmp;
276 tmp = virConnectClose(conn);
277 if (tmp < 0) {
278 ERROR("Failed to disconnect from the hypervisor");
279 ret = EXIT_FAILURE;
280 } else if (tmp > 0) {
281 ERROR("One or more references were leaked after "
282 "disconnect from the hypervisor");
283 ret = EXIT_FAILURE;
284 } else {
285 DEBUG("Connection successfully closed");
288 return ret;