Extend the -incoming option to allow an @MigrationChannel to be specified. This allows channels other than 'main' to be described on the command line, which will be needed for CPR.
Signed-off-by: Steve Sistare <steven.sist...@oracle.com> Acked-by: Peter Xu <pet...@redhat.com> --- migration/migration.c | 21 ++++++++++++++++----- qemu-options.hx | 21 +++++++++++++++++++++ system/vl.c | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/migration/migration.c b/migration/migration.c index b5ee98e..5f2540f 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -695,7 +695,8 @@ static void qemu_start_incoming_migration(const char *uri, bool has_channels, if (channels) { /* To verify that Migrate channel list has only item */ if (channels->next) { - error_setg(errp, "Channel list has more than one entries"); + error_setg(errp, "Channel list must have only one entry, " + "for type 'main'"); return; } addr = channels->value->addr; @@ -2054,6 +2055,7 @@ void qmp_migrate(const char *uri, bool has_channels, MigrationState *s = migrate_get_current(); g_autoptr(MigrationChannel) channel = NULL; MigrationAddress *addr = NULL; + MigrationChannel *channelv[MIGRATION_CHANNEL_TYPE__MAX] = { NULL }; /* * Having preliminary checks for uri and channel @@ -2064,12 +2066,21 @@ void qmp_migrate(const char *uri, bool has_channels, } if (channels) { - /* To verify that Migrate channel list has only item */ - if (channels->next) { - error_setg(errp, "Channel list has more than one entries"); + for ( ; channels; channels = channels->next) { + MigrationChannelType type = channels->value->channel_type; + + if (channelv[type]) { + error_setg(errp, "Channel list has more than one %s entry", + MigrationChannelType_str(type)); + return; + } + channelv[type] = channels->value; + } + addr = channelv[MIGRATION_CHANNEL_TYPE_MAIN]->addr; + if (!addr) { + error_setg(errp, "Channel list has no main entry"); return; } - addr = channels->value->addr; } if (uri) { diff --git a/qemu-options.hx b/qemu-options.hx index 90fad31..3d1af73 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4940,10 +4940,18 @@ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \ "-incoming exec:cmdline\n" \ " accept incoming migration on given file descriptor\n" \ " or from given external command\n" \ + "-incoming <channel>\n" \ + " accept incoming migration on the migration channel\n" \ "-incoming defer\n" \ " wait for the URI to be specified via migrate_incoming\n", QEMU_ARCH_ALL) SRST +The -incoming option specifies the migration channel for an incoming +migration. It may be used multiple times to specify multiple +migration channel types. The channel type is specified in <channel>, +or is 'main' for all other forms of -incoming. If multiple -incoming +options are specified for a channel type, the last one takes precedence. + ``-incoming tcp:[host]:port[,to=maxport][,ipv4=on|off][,ipv6=on|off]`` \ ``-incoming rdma:host:port[,ipv4=on|off][,ipv6=on|off]`` @@ -4963,6 +4971,19 @@ SRST Accept incoming migration as an output from specified external command. +``-incoming <channel>`` + Accept incoming migration on the migration channel. For the syntax + of <channel>, see the QAPI documentation of ``MigrationChannel``. + Examples: + :: + + -incoming '{"channel-type": "main", + "addr": { "transport": "socket", + "type": "unix", + "path": "my.sock" }}' + + -incoming main,addr.transport=socket,addr.type=unix,addr.path=my.sock + ``-incoming defer`` Wait for the URI to be specified via migrate\_incoming. The monitor can be used to change settings (such as migration parameters) prior diff --git a/system/vl.c b/system/vl.c index 61285ad..251efa0 100644 --- a/system/vl.c +++ b/system/vl.c @@ -123,6 +123,7 @@ #include "qapi/qapi-visit-block-core.h" #include "qapi/qapi-visit-compat.h" #include "qapi/qapi-visit-machine.h" +#include "qapi/qapi-visit-migration.h" #include "qapi/qapi-visit-ui.h" #include "qapi/qapi-commands-block-core.h" #include "qapi/qapi-commands-migration.h" @@ -159,6 +160,8 @@ typedef struct DeviceOption { static const char *cpu_option; static const char *mem_path; static const char *incoming; +static const char *incoming_str[MIGRATION_CHANNEL_TYPE__MAX]; +static MigrationChannel *incoming_channels[MIGRATION_CHANNEL_TYPE__MAX]; static const char *loadvm; static const char *accelerators; static bool have_custom_ram_size; @@ -1822,6 +1825,30 @@ static void object_option_add_visitor(Visitor *v) QTAILQ_INSERT_TAIL(&object_opts, opt, next); } +static void incoming_option_parse(const char *str) +{ + MigrationChannelType type = MIGRATION_CHANNEL_TYPE_MAIN; + MigrationChannel *channel; + Visitor *v; + + if (!strcmp(str, "defer")) { + channel = NULL; + } else if (migrate_is_uri(str)) { + migrate_uri_parse(str, &channel, &error_fatal); + } else { + v = qobject_input_visitor_new_str(str, "channel-type", &error_fatal); + visit_type_MigrationChannel(v, NULL, &channel, &error_fatal); + visit_free(v); + type = channel->channel_type; + } + + /* New incoming spec replaces the previous */ + qapi_free_MigrationChannel(incoming_channels[type]); + incoming_channels[type] = channel; + incoming_str[type] = str; + incoming = incoming_str[MIGRATION_CHANNEL_TYPE_MAIN]; +} + static void object_option_parse(const char *str) { QemuOpts *opts; @@ -2753,8 +2780,11 @@ void qmp_x_exit_preconfig(Error **errp) if (incoming) { Error *local_err = NULL; if (strcmp(incoming, "defer") != 0) { - qmp_migrate_incoming(incoming, false, NULL, true, true, - &local_err); + g_autofree MigrationChannelList *channels = + g_new0(MigrationChannelList, 1); + + channels->value = incoming_channels[MIGRATION_CHANNEL_TYPE_MAIN]; + qmp_migrate_incoming(NULL, true, channels, true, true, &local_err); if (local_err) { error_reportf_err(local_err, "-incoming %s: ", incoming); exit(1); @@ -3503,7 +3533,7 @@ void qemu_init(int argc, char **argv) if (!incoming) { runstate_set(RUN_STATE_INMIGRATE); } - incoming = optarg; + incoming_option_parse(optarg); break; case QEMU_OPTION_only_migratable: only_migratable = 1; -- 1.8.3.1