From: Juergen Gross <jgross@suse.com>
To: xen-devel@lists.xenproject.org
Cc: Juergen Gross <jgross@suse.com>,
Andrew Cooper <andrew.cooper3@citrix.com>,
George Dunlap <george.dunlap@citrix.com>,
Ian Jackson <iwj@xenproject.org>, Jan Beulich <jbeulich@suse.com>,
Julien Grall <julien@xen.org>,
Stefano Stabellini <sstabellini@kernel.org>, Wei Liu <wl@xen.org>,
Paul Durrant <paul@xen.org>, Julien Grall <jgrall@amazon.com>
Subject: [PATCH v11 07/27] tools/xenstore: add live update command to xenstore-control
Date: Thu, 14 Jan 2021 16:37:43 +0100 [thread overview]
Message-ID: <20210114153803.2591-8-jgross@suse.com> (raw)
In-Reply-To: <20210114153803.2591-1-jgross@suse.com>
Add the "live-update" command to xenstore-control enabling updating
xenstored to a new version in a running Xen system.
With -c <arg> it is possible to pass a different command line to the
new instance of xenstored. This will replace the command line used
for the invocation of the just running xenstored instance.
The running xenstored (or xenstore-stubdom) needs to support live
updating, of course.
For now just add a small dummy handler to C xenstore denying any
live update action.
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Paul Durrant <paul@xen.org>
Reviewed-by: Julien Grall <jgrall@amazon.com>
---
V2:
- add 0 byte after kernel chunk
- add comment regrading add_to_buf() semantics (Pawel Wieczorkiewicz)
- use %u for unsigned in format (Pawel Wieczorkiewicz)
- explain buffer size better (Pawel Wieczorkiewicz)
- add loop around "-s" option for client side retry in case of timeout
V3:
- add live-update command to docs/misc/xenstore.txt (Paul Durrant)
- fix indent (Paul Durrant)
V4:
- made several parameters const (Julien Grall)
- added more details to xenstore.txt (Julien Grall)
V5:
- set old_binary to NULL initially (Paul Durrant)
V6:
- use strerror(errno) in error message (Julien Grall)
V10:
- make binary specification mandatory (Andrew Cooper)
V11:
- add sleep(1) in timeout loop (Edwin Torok)
---
docs/misc/xenstore.txt | 21 ++
tools/xenstore/Makefile | 3 +-
tools/xenstore/xenstore_control.c | 333 +++++++++++++++++++++++++++--
tools/xenstore/xenstored_control.c | 30 +++
4 files changed, 370 insertions(+), 17 deletions(-)
diff --git a/docs/misc/xenstore.txt b/docs/misc/xenstore.txt
index 2081f20f55..1480742330 100644
--- a/docs/misc/xenstore.txt
+++ b/docs/misc/xenstore.txt
@@ -317,6 +317,27 @@ CONTROL <command>|[<parameters>|]
Current commands are:
check
checks xenstored innards
+ live-update|<params>|+
+ perform a live-update of the Xenstore daemon, only to
+ be used via xenstore-control command.
+ <params> are implementation specific and are used for
+ different steps of the live-update processing. Currently
+ supported <params> are:
+ -f <file> specify new daemon binary
+ -b <size> specify size of new stubdom binary
+ -d <chunk-size> <binary-chunk> transfer chunk of new
+ stubdom binary
+ -c <pars> specify new command line to use
+ -s [-t <sec>] [-F] start live update process (-t specifies
+ timeout in seconds to wait for active transactions
+ to finish, default is 60 seconds; -F will force
+ live update to happen even with running transactions
+ after timeout elapsed)
+ -a abort live update handling
+ All sub-options will return "OK" in case of success or an
+ error string in case of failure. -s can return "BUSY" in case
+ of an active transaction, a retry of -s can be done in that
+ case.
log|on
turn xenstore logging on
log|off
diff --git a/tools/xenstore/Makefile b/tools/xenstore/Makefile
index 9a0f0d012d..ab89e22d3a 100644
--- a/tools/xenstore/Makefile
+++ b/tools/xenstore/Makefile
@@ -11,6 +11,7 @@ CFLAGS += -include $(XEN_ROOT)/tools/config.h
CFLAGS += -I./include
CFLAGS += $(CFLAGS_libxenevtchn)
CFLAGS += $(CFLAGS_libxenctrl)
+CFLAGS += $(CFLAGS_libxenguest)
CFLAGS += $(CFLAGS_libxentoolcore)
CFLAGS += -DXEN_LIB_STORED="\"$(XEN_LIB_STORED)\""
CFLAGS += -DXEN_RUN_STORED="\"$(XEN_RUN_STORED)\""
@@ -81,7 +82,7 @@ xenstore: xenstore_client.o
$(CC) $< $(LDFLAGS) $(LDLIBS_libxenstore) $(LDLIBS_libxentoolcore) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
xenstore-control: xenstore_control.o
- $(CC) $< $(LDFLAGS) $(LDLIBS_libxenstore) $(LDLIBS_libxentoolcore) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
+ $(CC) $< $(LDFLAGS) $(LDLIBS_libxenstore) $(LDLIBS_libxenctrl) $(LDLIBS_libxenguest) $(LDLIBS_libxentoolcore) $(SOCKET_LIBS) -o $@ $(APPEND_LDFLAGS)
xs_tdb_dump: xs_tdb_dump.o utils.o tdb.o talloc.o
$(CC) $^ $(LDFLAGS) -o $@ $(APPEND_LDFLAGS)
diff --git a/tools/xenstore/xenstore_control.c b/tools/xenstore/xenstore_control.c
index afa04495a7..6031f216c7 100644
--- a/tools/xenstore/xenstore_control.c
+++ b/tools/xenstore/xenstore_control.c
@@ -1,9 +1,312 @@
+#define _GNU_SOURCE
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
+#include <xenctrl.h>
+#include <xenguest.h>
#include "xenstore.h"
+/* Add a string plus terminating 0 byte to buf, returning new len. */
+static int add_to_buf(char **buf, const char *val, int len)
+{
+ int vallen = strlen(val) + 1;
+
+ if (len < 0)
+ return -1;
+
+ *buf = realloc(*buf, len + vallen);
+ if (!*buf)
+ return -1;
+
+ strcpy(*buf + len, val);
+
+ return len + vallen;
+}
+
+static int live_update_start(struct xs_handle *xsh, bool force, unsigned int to)
+{
+ int len = 0;
+ char *buf = NULL, *ret;
+ time_t time_start;
+
+ if (asprintf(&ret, "%u", to) < 0)
+ return 1;
+ len = add_to_buf(&buf, "-s", len);
+ len = add_to_buf(&buf, "-t", len);
+ len = add_to_buf(&buf, ret, len);
+ free(ret);
+ if (force)
+ len = add_to_buf(&buf, "-F", len);
+ if (len < 0)
+ return 1;
+
+ for (time_start = time(NULL); time(NULL) - time_start < to;) {
+ ret = xs_control_command(xsh, "live-update", buf, len);
+ if (!ret)
+ goto err;
+ if (strcmp(ret, "BUSY"))
+ break;
+ sleep(1);
+ }
+
+ if (strcmp(ret, "OK"))
+ goto err;
+
+ free(buf);
+ free(ret);
+
+ return 0;
+
+ err:
+ fprintf(stderr, "Starting live update failed:\n%s\n",
+ ret ? : strerror(errno));
+ free(buf);
+ free(ret);
+
+ return 3;
+}
+
+static int live_update_cmdline(struct xs_handle *xsh, const char *cmdline)
+{
+ int len = 0, rc = 0;
+ char *buf = NULL, *ret;
+
+ len = add_to_buf(&buf, "-c", len);
+ len = add_to_buf(&buf, cmdline, len);
+ if (len < 0)
+ return 1;
+
+ ret = xs_control_command(xsh, "live-update", buf, len);
+ free(buf);
+ if (!ret || strcmp(ret, "OK")) {
+ fprintf(stderr, "Setting update binary failed:\n%s\n",
+ ret ? : strerror(errno));
+ rc = 3;
+ }
+ free(ret);
+
+ return rc;
+}
+
+static int send_kernel_blob(struct xs_handle *xsh, const char *binary)
+{
+ int rc = 0, len = 0;
+ xc_interface *xch;
+ struct xc_dom_image *dom;
+ char *ret, *buf = NULL;
+ size_t off, sz;
+#define BLOB_CHUNK_SZ 2048
+
+ xch = xc_interface_open(NULL, NULL, 0);
+ if (!xch) {
+ fprintf(stderr, "xc_interface_open() failed\n");
+ return 1;
+ }
+
+ dom = xc_dom_allocate(xch, NULL, NULL);
+ if (!dom) {
+ rc = 1;
+ goto out_close;
+ }
+
+ rc = xc_dom_kernel_file(dom, binary);
+ if (rc) {
+ rc = 1;
+ goto out_rel;
+ }
+
+ if (asprintf(&ret, "%zu", dom->kernel_size) < 0) {
+ rc = 1;
+ goto out_rel;
+ }
+ len = add_to_buf(&buf, "-b", len);
+ len = add_to_buf(&buf, ret, len);
+ free(ret);
+ if (len < 0) {
+ rc = 1;
+ goto out_rel;
+ }
+ ret = xs_control_command(xsh, "live-update", buf, len);
+ free(buf);
+ if (!ret || strcmp(ret, "OK")) {
+ fprintf(stderr, "Starting live update failed:\n%s\n",
+ ret ? : strerror(errno));
+ rc = 3;
+ }
+ free(ret);
+ if (rc)
+ goto out_rel;
+
+ /* buf capable to hold "-d" <1..2048> BLOB_CHUNK_SZ and a terminating 0. */
+ buf = malloc(3 + 5 + BLOB_CHUNK_SZ + 1);
+ if (!buf) {
+ rc = 1;
+ goto out_rel;
+ }
+
+ strcpy(buf, "-d");
+ sz = BLOB_CHUNK_SZ;
+ for (off = 0; off < dom->kernel_size; off += BLOB_CHUNK_SZ) {
+ if (dom->kernel_size - off < BLOB_CHUNK_SZ)
+ sz = dom->kernel_size - off;
+ sprintf(buf + 3, "%zu", sz);
+ len = 3 + strlen(buf + 3) + 1;
+ memcpy(buf + len, dom->kernel_blob + off, sz);
+ buf[len + sz] = 0;
+ len += sz + 1;
+ ret = xs_control_command(xsh, "live-update", buf, len);
+ if (!ret || strcmp(ret, "OK")) {
+ fprintf(stderr, "Transfer of new binary failed:\n%s\n",
+ ret ? : strerror(errno));
+ rc = 3;
+ free(ret);
+ break;
+ }
+ free(ret);
+ }
+
+ free(buf);
+
+ out_rel:
+ xc_dom_release(dom);
+
+ out_close:
+ xc_interface_close(xch);
+
+ return rc;
+}
+
+/*
+ * Live update of Xenstore stubdom
+ *
+ * Sequence of actions:
+ * 1. transfer new stubdom binary
+ * a) specify size
+ * b) transfer unpacked binary in chunks
+ * 2. transfer new cmdline (optional)
+ * 3. start update (includes flags)
+ */
+static int live_update_stubdom(struct xs_handle *xsh, const char *binary,
+ const char *cmdline, bool force, unsigned int to)
+{
+ int rc;
+
+ rc = send_kernel_blob(xsh, binary);
+ if (rc)
+ goto abort;
+
+ if (cmdline) {
+ rc = live_update_cmdline(xsh, cmdline);
+ if (rc)
+ goto abort;
+ }
+
+ rc = live_update_start(xsh, force, to);
+ if (rc)
+ goto abort;
+
+ return 0;
+
+ abort:
+ xs_control_command(xsh, "live-update", "-a", 3);
+ return rc;
+}
+
+/*
+ * Live update of Xenstore daemon
+ *
+ * Sequence of actions:
+ * 1. transfer new binary filename
+ * 2. transfer new cmdline (optional)
+ * 3. start update (includes flags)
+ */
+static int live_update_daemon(struct xs_handle *xsh, const char *binary,
+ const char *cmdline, bool force, unsigned int to)
+{
+ int len = 0, rc;
+ char *buf = NULL, *ret;
+
+ len = add_to_buf(&buf, "-f", len);
+ len = add_to_buf(&buf, binary, len);
+ if (len < 0)
+ return 1;
+ ret = xs_control_command(xsh, "live-update", buf, len);
+ free(buf);
+ if (!ret || strcmp(ret, "OK")) {
+ fprintf(stderr, "Setting update binary failed:\n%s\n",
+ ret ? : strerror(errno));
+ free(ret);
+ return 3;
+ }
+ free(ret);
+
+ if (cmdline) {
+ rc = live_update_cmdline(xsh, cmdline);
+ if (rc)
+ goto abort;
+ }
+
+ rc = live_update_start(xsh, force, to);
+ if (rc)
+ goto abort;
+
+ return 0;
+
+ abort:
+ xs_control_command(xsh, "live-update", "-a", 3);
+ return rc;
+}
+
+static int live_update(struct xs_handle *xsh, int argc, char **argv)
+{
+ int rc = 0;
+ unsigned int i, to = 60;
+ char *binary = NULL, *cmdline = NULL, *val;
+ bool force = false;
+
+ for (i = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "-c")) {
+ i++;
+ if (i == argc) {
+ fprintf(stderr, "Missing command line value\n");
+ rc = 2;
+ goto out;
+ }
+ cmdline = argv[i];
+ } else if (!strcmp(argv[i], "-t")) {
+ i++;
+ if (i == argc) {
+ fprintf(stderr, "Missing timeout value\n");
+ rc = 2;
+ goto out;
+ }
+ to = atoi(argv[i]);
+ } else if (!strcmp(argv[i], "-F"))
+ force = true;
+ else
+ binary = argv[i];
+ }
+
+ if (!binary) {
+ fprintf(stderr, "Missing binary specification\n");
+ rc = 2;
+ goto out;
+ }
+
+ val = xs_read(xsh, XBT_NULL, "/tool/xenstored/domid", &i);
+ if (val)
+ rc = live_update_stubdom(xsh, binary, cmdline, force, to);
+ else
+ rc = live_update_daemon(xsh, binary, cmdline, force, to);
+
+ free(val);
+
+ out:
+ return rc;
+}
int main(int argc, char **argv)
{
@@ -20,22 +323,6 @@ int main(int argc, char **argv)
goto out;
}
- for (p = 2; p < argc; p++)
- len += strlen(argv[p]) + 1;
- if (len) {
- par = malloc(len);
- if (!par) {
- fprintf(stderr, "Allocation error.\n");
- rc = 1;
- goto out;
- }
- len = 0;
- for (p = 2; p < argc; p++) {
- memcpy(par + len, argv[p], strlen(argv[p]) + 1);
- len += strlen(argv[p]) + 1;
- }
- }
-
xsh = xs_open(0);
if (xsh == NULL) {
fprintf(stderr, "Failed to contact Xenstored.\n");
@@ -43,6 +330,19 @@ int main(int argc, char **argv)
goto out;
}
+ if (!strcmp(argv[1], "live-update")) {
+ rc = live_update(xsh, argc - 2, argv + 2);
+ goto out_close;
+ }
+
+ for (p = 2; p < argc; p++)
+ len = add_to_buf(&par, argv[p], len);
+ if (len < 0) {
+ fprintf(stderr, "Allocation error.\n");
+ rc = 1;
+ goto out_close;
+ }
+
ret = xs_control_command(xsh, argv[1], par, len);
if (!ret) {
rc = 3;
@@ -59,6 +359,7 @@ int main(int argc, char **argv)
} else if (strlen(ret) > 0)
printf("%s\n", ret);
+ out_close:
xs_close(xsh);
out:
diff --git a/tools/xenstore/xenstored_control.c b/tools/xenstore/xenstored_control.c
index 8d29db8270..00fda5acdb 100644
--- a/tools/xenstore/xenstored_control.c
+++ b/tools/xenstore/xenstored_control.c
@@ -149,11 +149,41 @@ static int do_control_print(void *ctx, struct connection *conn,
return 0;
}
+static int do_control_lu(void *ctx, struct connection *conn,
+ char **vec, int num)
+{
+ const char *resp;
+
+ resp = talloc_strdup(ctx, "NYI");
+ send_reply(conn, XS_CONTROL, resp, strlen(resp) + 1);
+ return 0;
+}
+
static int do_control_help(void *, struct connection *, char **, int);
static struct cmd_s cmds[] = {
{ "check", do_control_check, "" },
{ "log", do_control_log, "on|off" },
+
+ /*
+ * The parameters are those of the xenstore-control utility!
+ * Depending on environment (Mini-OS or daemon) the live-update
+ * sequence is split into several sub-operations:
+ * 1. Specification of new binary
+ * daemon: -f <filename>
+ * Mini-OS: -b <binary-size>
+ * -d <size> <data-bytes> (multiple of those)
+ * 2. New command-line (optional): -c <cmdline>
+ * 3. Start of update: -s [-F] [-t <timeout>]
+ * Any sub-operation needs to respond with the string "OK" in case
+ * of success, any other response indicates failure.
+ * A started live-update sequence can be aborted via "-a" (not
+ * needed in case of failure for the first or last live-update
+ * sub-operation).
+ */
+ { "live-update", do_control_lu,
+ "[-c <cmdline>] [-F] [-t <timeout>] <file>\n"
+ " Default timeout is 60 seconds.", 4 },
#ifdef __MINIOS__
{ "memreport", do_control_memreport, "" },
#else
--
2.26.2
next prev parent reply other threads:[~2021-01-14 15:38 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-14 15:37 [PATCH v11 00/27] tools/xenstore: support live update for xenstored Juergen Gross
2021-01-14 15:37 ` [PATCH v11 01/27] tools/libxenevtchn: switch to standard xen coding style Juergen Gross
2021-01-14 19:07 ` Andrew Cooper
2021-01-15 6:13 ` Jürgen Groß
2021-01-14 15:37 ` [PATCH v11 02/27] tools/libxenevtchn: rename open_flags to flags Juergen Gross
2021-01-14 19:22 ` Andrew Cooper
2021-01-15 6:14 ` Jürgen Groß
2021-01-14 15:37 ` [PATCH v11 03/27] tools/libxenevtchn: check xenevtchn_open() flags for not supported bits Juergen Gross
2021-01-14 19:24 ` Andrew Cooper
2021-01-15 6:19 ` Jürgen Groß
2021-01-14 15:37 ` [PATCH v11 04/27] tools/libxenevtchn: propagate xenevtchn_open() flags parameter Juergen Gross
2021-01-14 19:26 ` Andrew Cooper
2021-01-14 15:37 ` [PATCH v11 05/27] tools/libxenevtchn: add possibility to not close file descriptor on exec Juergen Gross
2021-01-15 1:01 ` Andrew Cooper
2021-01-15 7:11 ` Jürgen Groß
2021-01-14 15:37 ` [PATCH v11 06/27] tools/xenstore: refactor XS_CONTROL handling Juergen Gross
2021-01-14 15:37 ` Juergen Gross [this message]
2021-01-14 15:37 ` [PATCH v11 08/27] tools/xenstore: add basic live-update command parsing Juergen Gross
2021-01-14 15:37 ` [PATCH v11 09/27] tools/xenstore: introduce live update status block Juergen Gross
2021-01-14 15:37 ` [PATCH v11 10/27] tools/xenstore: save new binary for live update Juergen Gross
2021-01-14 15:37 ` [PATCH v11 11/27] tools/xenstore: add command line handling " Juergen Gross
2021-01-14 15:37 ` [PATCH v11 12/27] tools/xenstore: add support for delaying execution of a xenstore request Juergen Gross
2021-01-14 15:37 ` [PATCH v11 13/27] tools/xenstore: add the basic framework for doing the live update Juergen Gross
2021-01-14 15:37 ` [PATCH v11 14/27] tools/xenstore: allow live update only with no transaction active Juergen Gross
2021-01-14 15:37 ` [PATCH v11 15/27] docs: update the xenstore migration stream documentation Juergen Gross
2021-01-14 15:37 ` [PATCH v11 16/27] tools/xenstore: add include file for state structure definitions Juergen Gross
2021-01-14 15:37 ` [PATCH v11 17/27] tools/xenstore: dump the xenstore state for live update Juergen Gross
2021-01-14 15:37 ` [PATCH v11 18/27] tools/xenstore: handle CLOEXEC flag for local files and pipes Juergen Gross
2021-01-14 15:37 ` [PATCH v11 19/27] tools/xenstore: split off domain introduction from do_introduce() Juergen Gross
2021-01-14 15:37 ` [PATCH v11 20/27] tools/xenstore: evaluate the live update flag when starting Juergen Gross
2021-01-14 15:37 ` [PATCH v11 21/27] tools/xenstore: read internal state when doing live upgrade Juergen Gross
2021-01-14 15:37 ` [PATCH v11 22/27] tools/xenstore: add reading global state for live update Juergen Gross
2021-01-14 15:37 ` [PATCH v11 23/27] tools/xenstore: add read connection " Juergen Gross
2021-01-14 15:38 ` [PATCH v11 24/27] tools/xenstore: add read node " Juergen Gross
2021-01-14 15:38 ` [PATCH v11 25/27] tools/xenstore: add read watch " Juergen Gross
2021-01-14 15:38 ` [PATCH v11 26/27] tools/xenstore: handle dying domains in " Juergen Gross
2021-01-14 15:38 ` [PATCH v11 27/27] tools/xenstore: activate new binary for " Juergen Gross
2021-01-14 16:48 ` [PATCH v11 00/27] tools/xenstore: support live update for xenstored Jürgen Groß
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210114153803.2591-8-jgross@suse.com \
--to=jgross@suse.com \
--cc=andrew.cooper3@citrix.com \
--cc=george.dunlap@citrix.com \
--cc=iwj@xenproject.org \
--cc=jbeulich@suse.com \
--cc=jgrall@amazon.com \
--cc=julien@xen.org \
--cc=paul@xen.org \
--cc=sstabellini@kernel.org \
--cc=wl@xen.org \
--cc=xen-devel@lists.xenproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.