]> xenbits.xensource.com Git - libvirt.git/commitdiff
examples: Resurrect domsuspend example
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 13 Dec 2013 11:54:10 +0000 (12:54 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 24 Dec 2013 16:17:35 +0000 (17:17 +0100)
This partially reverts 5eb4b04211 and 62774afb6ba8.

Rewrite the domsuspend example from scratch. This time do it right.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
.gitignore
Makefile.am
cfg.mk
configure.ac
examples/domsuspend/Makefile.am [new file with mode: 0644]
examples/domsuspend/suspend.c [new file with mode: 0644]
libvirt.spec.in

index d5a6cf52b11e87980c102fb8105db4fdb5765608..496c2ef03e0f2b4780d0b8eee8b28940ebc1ab6a 100644 (file)
@@ -71,6 +71,7 @@
 /docs/todo.html.in
 /examples/object-events/event-test
 /examples/dominfo/info1
+/examples/domsuspend/suspend
 /examples/hellolibvirt/hellolibvirt
 /examples/openauth/openauth
 /gnulib/lib/*
index 88c70734b904f38cc44b0ccb36b71005062be70a..eb88fee66c9714063ce3e209a279c6944fe2ea1a 100644 (file)
@@ -21,8 +21,8 @@ GENHTML = genhtml
 
 SUBDIRS = . gnulib/lib include src daemon tools docs gnulib/tests \
   tests po examples/object-events examples/hellolibvirt \
-  examples/dominfo examples/apparmor examples/xml/nwfilter \
-  examples/openauth examples/systemtap
+  examples/dominfo examples/domsuspend examples/apparmor \
+  examples/xml/nwfilter examples/openauth examples/systemtap
 
 ACLOCAL_AMFLAGS = -I m4
 
diff --git a/cfg.mk b/cfg.mk
index 9a0665061679406d75bbd02b57e2623708144652..5591065afd55861715255570f9e27252e419603e 100644 (file)
--- a/cfg.mk
+++ b/cfg.mk
@@ -1003,7 +1003,7 @@ exclude_file_name_regexp--sc_prohibit_sprintf = \
 exclude_file_name_regexp--sc_prohibit_strncpy = ^src/util/virstring\.c$$
 
 exclude_file_name_regexp--sc_prohibit_strtol = \
-  ^src/(util/virsexpr|(vbox|xen|xenxs)/.*)\.c$$
+  ^(src/(util/virsexpr|(vbox|xen|xenxs)/.*)\.c)|(examples/domsuspend/suspend.c)$$
 
 exclude_file_name_regexp--sc_prohibit_xmlGetProp = ^src/util/virxml\.c$$
 
index ddbcc8ec1f5cbf1d1b85bdcfe5103b1e18e0e17b..2622dfd5306ac8c8c698fb42075a50ee21c073bb 100644 (file)
@@ -2555,6 +2555,7 @@ AC_CONFIG_FILES([\
         tests/Makefile \
         examples/apparmor/Makefile \
         examples/object-events/Makefile \
+        examples/domsuspend/Makefile \
         examples/dominfo/Makefile \
         examples/openauth/Makefile \
         examples/hellolibvirt/Makefile \
diff --git a/examples/domsuspend/Makefile.am b/examples/domsuspend/Makefile.am
new file mode 100644 (file)
index 0000000..b8e65f2
--- /dev/null
@@ -0,0 +1,27 @@
+## Process this file with automake to produce Makefile.in
+
+## Copyright (C) 2013 Red Hat, Inc.
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
+LDADDS = $(STATIC_BINARIES) $(WARN_CFLAGS) $(top_builddir)/src/libvirt.la \
+       $(COVERAGE_LDFLAGS)
+
+noinst_PROGRAMS=suspend
+
+suspend_SOURCES=suspend.c
+suspend_LDFLAGS=
+suspend_LDADD= $(LDADDS)
diff --git a/examples/domsuspend/suspend.c b/examples/domsuspend/suspend.c
new file mode 100644 (file)
index 0000000..f61a5d1
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * suspend.c: Demo program showing how to suspend a domain
+ *
+ * Copyright (C) 2006-2013 Red Hat, Inc.
+ * Copyright (C) 2006 Daniel P. Berrange
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Author: Michal Privoznik <mprivozn@redhat.com>
+ */
+
+#include <errno.h>
+#include <getopt.h>
+#include <libvirt/libvirt.h>
+#include <libvirt/virterror.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int debug;
+
+#define ERROR(...)                                              \
+do {                                                            \
+    fprintf(stderr, "ERROR %s:%d : ", __FUNCTION__, __LINE__);  \
+    fprintf(stderr, __VA_ARGS__);                               \
+    fprintf(stderr, "\n");                                      \
+} while (0)
+
+#define DEBUG(...)                                              \
+do {                                                            \
+    if (!debug)                                                 \
+        break;                                                  \
+    fprintf(stderr, "DEBUG %s:%d : ", __FUNCTION__, __LINE__);  \
+    fprintf(stderr, __VA_ARGS__);                               \
+    fprintf(stderr, "\n");                                      \
+} while (0)
+
+static void
+print_usage(const char *progname)
+{
+    const char *unified_progname;
+
+    if (!(unified_progname = strrchr(progname, '/')))
+        unified_progname = progname;
+    else
+        unified_progname++;
+
+    printf("\n%s [options] [domain name]\n\n"
+           "  options:\n"
+           "    -d | --debug        enable debug printings\n"
+           "    -h | --help         print this help\n"
+           "    -c | --connect=URI  hypervisor connection URI\n"
+           "    -s | --seconds=X    suspend domain for X seconds (default 1)\n",
+           unified_progname);
+}
+
+static int
+parse_argv(int argc, char *argv[],
+           const char **uri,
+           const char **dom_name,
+           unsigned int *seconds)
+{
+    int ret = -1;
+    int arg;
+    unsigned long val;
+    char *p;
+    struct option opt[] = {
+        {"debug", no_argument, NULL, 'd'},
+        {"help", no_argument, NULL, 'h'},
+        {"connect", required_argument, NULL, 'c'},
+        {"seconds", required_argument, NULL, 's'},
+        {NULL, 0, NULL, 0}
+    };
+
+    while ((arg = getopt_long(argc, argv, "+:dhc:s:", opt, NULL)) != -1) {
+        switch (arg) {
+        case 'd':
+            debug = 1;
+            break;
+        case 'h':
+            print_usage(argv[0]);
+            exit(EXIT_SUCCESS);
+            break;
+        case 'c':
+            *uri = optarg;
+            break;
+        case 's':
+            /* strtoul man page suggest clearing errno prior to call */
+            errno = 0;
+            val = strtoul(optarg, &p, 10);
+            if (errno || *p || p == optarg) {
+                ERROR("Invalid number: '%s'", optarg);
+                goto cleanup;
+            }
+            *seconds = val;
+            if (*seconds != val) {
+                ERROR("Integer overflow: %ld", val);
+                goto cleanup;
+            }
+            break;
+        case ':':
+            ERROR("option '-%c' requires an argument", optopt);
+            exit(EXIT_FAILURE);
+        case '?':
+            if (optopt)
+                ERROR("unsupported option '-%c'. See --help.", optopt);
+            else
+                ERROR("unsupported option '%s'. See --help.", argv[optind - 1]);
+            exit(EXIT_FAILURE);
+        default:
+            ERROR("unknown option");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (argc > optind)
+        *dom_name = argv[optind];
+
+    ret = 0;
+cleanup:
+    return ret;
+}
+
+static int
+fetch_domains(virConnectPtr conn)
+{
+    int num_domains, ret = -1;
+    virDomainPtr *domains = NULL;
+    size_t i;
+    const int list_flags = VIR_CONNECT_LIST_DOMAINS_ACTIVE;
+
+    DEBUG("Fetching list of running domains");
+    num_domains = virConnectListAllDomains(conn, &domains, list_flags);
+
+    DEBUG("num_domains=%d", num_domains);
+    if (num_domains < 0) {
+        ERROR("Unable to fetch list of running domains");
+        goto cleanup;
+    }
+
+    printf("Running domains:\n");
+    printf("----------------\n");
+    for (i = 0; i < num_domains; i++) {
+        virDomainPtr dom = domains[i];
+        const char *dom_name = virDomainGetName(dom);
+        printf("%s\n", dom_name);
+        virDomainFree(dom);
+    }
+
+    ret = 0;
+cleanup:
+    free(domains);
+    return ret;
+}
+
+static int
+suspend_and_resume(virConnectPtr conn,
+                   const char *dom_name,
+                   unsigned int seconds)
+{
+    int ret = -1;
+    virDomainPtr dom;
+    virDomainInfo dom_info;
+
+    if (!(dom = virDomainLookupByName(conn, dom_name))) {
+        ERROR("Unable to find domain '%s'", dom_name);
+        goto cleanup;
+    }
+
+    if (virDomainGetInfo(dom, &dom_info) < 0) {
+        ERROR("Unable to get domain info");
+        goto cleanup;
+    }
+
+    DEBUG("Domain state %d", dom_info.state);
+
+    switch (dom_info.state) {
+    case VIR_DOMAIN_NOSTATE:
+    case VIR_DOMAIN_RUNNING:
+    case VIR_DOMAIN_BLOCKED:
+        /* In these states the domain can be suspended */
+        DEBUG("Suspending domain");
+        if (virDomainSuspend(dom) < 0) {
+            ERROR("Unable to suspend domain");
+            goto cleanup;
+        }
+
+        DEBUG("Domain suspended. Entering sleep for %u seconds.", seconds);
+        sleep(seconds);
+        DEBUG("Sleeping done. Resuming the domain.");
+
+        if (virDomainResume(dom) < 0) {
+            ERROR("Unable to resume domain");
+            goto cleanup;
+        }
+        break;
+
+    default:
+        /* In all other states domain can't be suspended */
+        ERROR("Domain is not in a state where it can be suspended: %d",
+              dom_info.state);
+        goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    if (dom)
+        virDomainFree(dom);
+    return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
+    int ret = EXIT_FAILURE;
+    virConnectPtr conn = NULL;
+    const char *uri = NULL;
+    const char *dom_name = NULL;
+    unsigned int seconds = 1; /* Suspend domain for this long */
+    const int connect_flags = 0; /* No connect flags for now */
+
+    if (parse_argv(argc, argv, &uri, &dom_name, &seconds) < 0)
+        goto cleanup;
+
+    DEBUG("Proceeding with uri=%s dom_name=%s seconds=%u",
+          uri, dom_name, seconds);
+
+    if (!(conn = virConnectOpenAuth(uri,
+                                    virConnectAuthPtrDefault,
+                                    connect_flags))) {
+        ERROR("Failed to connect to hypervisor");
+        goto cleanup;
+    }
+
+    DEBUG("Successfully connected");
+
+    if (!dom_name) {
+        if (fetch_domains(conn) == 0)
+            ret = EXIT_SUCCESS;
+        goto cleanup;
+    }
+
+    if (suspend_and_resume(conn, dom_name, seconds) < 0)
+        goto cleanup;
+
+    ret = EXIT_SUCCESS;
+cleanup:
+    if (conn) {
+        int tmp;
+        tmp = virConnectClose(conn);
+        if (tmp < 0) {
+            ERROR("Failed to disconnect from the hypervisor");
+            ret = EXIT_FAILURE;
+        } else if (tmp > 0) {
+            ERROR("One or more references were leaked after "
+                  "disconnect from the hypervisor");
+            ret = EXIT_FAILURE;
+        } else {
+            DEBUG("Connection successfully closed");
+        }
+    }
+    return ret;
+}
index 3f8db094301fee79313f1c1bdab1d27ad2e5d357..0b530fe43f0b8727679a92a0a0c5c750e49ac8b8 100644 (file)
@@ -1430,7 +1430,7 @@ rm -fr %{buildroot}
 # on RHEL 5, thus we need to expand it here.
 make install DESTDIR=%{?buildroot} SYSTEMD_UNIT_DIR=%{_unitdir}
 
-for i in object-events dominfo hellolibvirt openauth xml/nwfilter systemtap
+for i in object-events dominfo domsuspend hellolibvirt openauth xml/nwfilter systemtap
 do
   (cd examples/$i ; make clean ; rm -rf .deps .libs Makefile Makefile.in)
 done
@@ -2142,6 +2142,7 @@ exit 0
 %doc examples/hellolibvirt
 %doc examples/object-events
 %doc examples/dominfo
+%doc examples/domsuspend
 %doc examples/openauth
 %doc examples/xml
 %doc examples/systemtap