1 /*
2 * HMP commands related to migration
3 *
4 * Copyright IBM, Corp. 2011
5 *
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 * Contributions after 2012-01-13 are licensed under the terms of the
13 * GNU GPL, version 2 or (at your option) any later version.
14 */
15
16 #include "qemu/osdep.h"
17 #include "block/qapi.h"
18 #include "migration/snapshot.h"
19 #include "monitor/hmp.h"
20 #include "monitor/monitor.h"
21 #include "qapi/error.h"
22 #include "qapi/qapi-commands-migration.h"
23 #include "qapi/qapi-visit-migration.h"
24 #include "qobject/qdict.h"
25 #include "qapi/string-input-visitor.h"
26 #include "qapi/string-output-visitor.h"
27 #include "qemu/cutils.h"
28 #include "qemu/error-report.h"
29 #include "qemu/sockets.h"
30 #include "system/runstate.h"
31 #include "ui/qemu-spice.h"
32 #include "system/system.h"
33 #include "options.h"
34 #include "migration.h"
35
migration_global_dump(Monitor * mon)36 static void migration_global_dump(Monitor *mon)
37 {
38 MigrationState *ms = migrate_get_current();
39
40 monitor_printf(mon, "Globals:\n");
41 monitor_printf(mon, " store-global-state: %s\n",
42 ms->store_global_state ? "on" : "off");
43 monitor_printf(mon, " only-migratable: %s\n",
44 only_migratable ? "on" : "off");
45 monitor_printf(mon, " send-configuration: %s\n",
46 ms->send_configuration ? "on" : "off");
47 monitor_printf(mon, " send-section-footer: %s\n",
48 ms->send_section_footer ? "on" : "off");
49 monitor_printf(mon, " send-switchover-start: %s\n",
50 ms->send_switchover_start ? "on" : "off");
51 monitor_printf(mon, " clear-bitmap-shift: %u\n",
52 ms->clear_bitmap_shift);
53 }
54
hmp_info_migrate(Monitor * mon,const QDict * qdict)55 void hmp_info_migrate(Monitor *mon, const QDict *qdict)
56 {
57 bool show_all = qdict_get_try_bool(qdict, "all", false);
58 MigrationInfo *info;
59
60 info = qmp_query_migrate(NULL);
61
62 if (info->blocked_reasons) {
63 strList *reasons = info->blocked_reasons;
64 monitor_printf(mon, "Outgoing migration blocked:\n");
65 while (reasons) {
66 monitor_printf(mon, " %s\n", reasons->value);
67 reasons = reasons->next;
68 }
69 }
70
71 if (info->has_status) {
72 monitor_printf(mon, "Status: %s",
73 MigrationStatus_str(info->status));
74 if (info->status == MIGRATION_STATUS_FAILED && info->error_desc) {
75 monitor_printf(mon, " (%s)\n", info->error_desc);
76 } else {
77 monitor_printf(mon, "\n");
78 }
79
80 if (info->total_time) {
81 monitor_printf(mon, "Time (ms): total=%" PRIu64,
82 info->total_time);
83 if (info->has_setup_time) {
84 monitor_printf(mon, ", setup=%" PRIu64,
85 info->setup_time);
86 }
87 if (info->has_expected_downtime) {
88 monitor_printf(mon, ", exp_down=%" PRIu64,
89 info->expected_downtime);
90 }
91 if (info->has_downtime) {
92 monitor_printf(mon, ", down=%" PRIu64,
93 info->downtime);
94 }
95 monitor_printf(mon, "\n");
96 }
97 }
98
99 if (info->has_socket_address) {
100 SocketAddressList *addr;
101
102 monitor_printf(mon, "Sockets: [\n");
103
104 for (addr = info->socket_address; addr; addr = addr->next) {
105 char *s = socket_uri(addr->value);
106 monitor_printf(mon, "\t%s\n", s);
107 g_free(s);
108 }
109 monitor_printf(mon, "]\n");
110 }
111
112 if (info->ram) {
113 monitor_printf(mon, "RAM info:\n");
114 monitor_printf(mon, " Throughput (Mbps): %0.2f\n",
115 info->ram->mbps);
116 monitor_printf(mon, " Sizes (KiB): pagesize=%" PRIu64
117 ", total=%" PRIu64 ",\n",
118 info->ram->page_size >> 10,
119 info->ram->total >> 10);
120 monitor_printf(mon, " transferred=%" PRIu64
121 ", remain=%" PRIu64 ",\n",
122 info->ram->transferred >> 10,
123 info->ram->remaining >> 10);
124 monitor_printf(mon, " precopy=%" PRIu64
125 ", multifd=%" PRIu64
126 ", postcopy=%" PRIu64,
127 info->ram->precopy_bytes >> 10,
128 info->ram->multifd_bytes >> 10,
129 info->ram->postcopy_bytes >> 10);
130
131 if (info->vfio) {
132 monitor_printf(mon, ", vfio=%" PRIu64,
133 info->vfio->transferred >> 10);
134 }
135 monitor_printf(mon, "\n");
136
137 monitor_printf(mon, " Pages: normal=%" PRIu64 ", zero=%" PRIu64
138 ", rate_per_sec=%" PRIu64 "\n",
139 info->ram->normal,
140 info->ram->duplicate,
141 info->ram->pages_per_second);
142 monitor_printf(mon, " Others: dirty_syncs=%" PRIu64,
143 info->ram->dirty_sync_count);
144
145 if (info->ram->dirty_pages_rate) {
146 monitor_printf(mon, ", dirty_pages_rate=%" PRIu64,
147 info->ram->dirty_pages_rate);
148 }
149 if (info->ram->postcopy_requests) {
150 monitor_printf(mon, ", postcopy_req=%" PRIu64,
151 info->ram->postcopy_requests);
152 }
153 if (info->ram->downtime_bytes) {
154 monitor_printf(mon, ", downtime_ram=%" PRIu64,
155 info->ram->downtime_bytes);
156 }
157 if (info->ram->dirty_sync_missed_zero_copy) {
158 monitor_printf(mon, ", zerocopy_fallbacks=%" PRIu64,
159 info->ram->dirty_sync_missed_zero_copy);
160 }
161 monitor_printf(mon, "\n");
162 }
163
164 if (!show_all) {
165 goto out;
166 }
167
168 migration_global_dump(mon);
169
170 if (info->xbzrle_cache) {
171 monitor_printf(mon, "XBZRLE: size=%" PRIu64
172 ", transferred=%" PRIu64
173 ", pages=%" PRIu64
174 ", miss=%" PRIu64 "\n"
175 " miss_rate=%0.2f"
176 ", encode_rate=%0.2f"
177 ", overflow=%" PRIu64 "\n",
178 info->xbzrle_cache->cache_size,
179 info->xbzrle_cache->bytes,
180 info->xbzrle_cache->pages,
181 info->xbzrle_cache->cache_miss,
182 info->xbzrle_cache->cache_miss_rate,
183 info->xbzrle_cache->encoding_rate,
184 info->xbzrle_cache->overflow);
185 }
186
187 if (info->has_cpu_throttle_percentage) {
188 monitor_printf(mon, "CPU Throttle (%%): %" PRIu64 "\n",
189 info->cpu_throttle_percentage);
190 }
191
192 if (info->has_dirty_limit_throttle_time_per_round) {
193 monitor_printf(mon, "Dirty-limit Throttle (us): %" PRIu64 "\n",
194 info->dirty_limit_throttle_time_per_round);
195 }
196
197 if (info->has_dirty_limit_ring_full_time) {
198 monitor_printf(mon, "Dirty-limit Ring Full (us): %" PRIu64 "\n",
199 info->dirty_limit_ring_full_time);
200 }
201
202 if (info->has_postcopy_blocktime) {
203 monitor_printf(mon, "Postcopy Blocktime (ms): %" PRIu32 "\n",
204 info->postcopy_blocktime);
205 }
206
207 if (info->has_postcopy_vcpu_blocktime) {
208 Visitor *v;
209 char *str;
210 v = string_output_visitor_new(false, &str);
211 visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime,
212 &error_abort);
213 visit_complete(v, &str);
214 monitor_printf(mon, "Postcopy vCPU Blocktime: %s\n", str);
215 g_free(str);
216 visit_free(v);
217 }
218
219 out:
220 qapi_free_MigrationInfo(info);
221 }
222
hmp_info_migrate_capabilities(Monitor * mon,const QDict * qdict)223 void hmp_info_migrate_capabilities(Monitor *mon, const QDict *qdict)
224 {
225 MigrationCapabilityStatusList *caps, *cap;
226
227 caps = qmp_query_migrate_capabilities(NULL);
228
229 if (caps) {
230 for (cap = caps; cap; cap = cap->next) {
231 monitor_printf(mon, "%s: %s\n",
232 MigrationCapability_str(cap->value->capability),
233 cap->value->state ? "on" : "off");
234 }
235 }
236
237 qapi_free_MigrationCapabilityStatusList(caps);
238 }
239
hmp_info_migrate_parameters(Monitor * mon,const QDict * qdict)240 void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
241 {
242 MigrationParameters *params;
243
244 params = qmp_query_migrate_parameters(NULL);
245
246 if (params) {
247 monitor_printf(mon, "%s: %" PRIu64 " ms\n",
248 MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_INITIAL),
249 params->announce_initial);
250 monitor_printf(mon, "%s: %" PRIu64 " ms\n",
251 MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_MAX),
252 params->announce_max);
253 monitor_printf(mon, "%s: %" PRIu64 "\n",
254 MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_ROUNDS),
255 params->announce_rounds);
256 monitor_printf(mon, "%s: %" PRIu64 " ms\n",
257 MigrationParameter_str(MIGRATION_PARAMETER_ANNOUNCE_STEP),
258 params->announce_step);
259 assert(params->has_throttle_trigger_threshold);
260 monitor_printf(mon, "%s: %u\n",
261 MigrationParameter_str(MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD),
262 params->throttle_trigger_threshold);
263 assert(params->has_cpu_throttle_initial);
264 monitor_printf(mon, "%s: %u\n",
265 MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL),
266 params->cpu_throttle_initial);
267 assert(params->has_cpu_throttle_increment);
268 monitor_printf(mon, "%s: %u\n",
269 MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT),
270 params->cpu_throttle_increment);
271 assert(params->has_cpu_throttle_tailslow);
272 monitor_printf(mon, "%s: %s\n",
273 MigrationParameter_str(MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW),
274 params->cpu_throttle_tailslow ? "on" : "off");
275 assert(params->has_max_cpu_throttle);
276 monitor_printf(mon, "%s: %u\n",
277 MigrationParameter_str(MIGRATION_PARAMETER_MAX_CPU_THROTTLE),
278 params->max_cpu_throttle);
279 assert(params->tls_creds);
280 monitor_printf(mon, "%s: '%s'\n",
281 MigrationParameter_str(MIGRATION_PARAMETER_TLS_CREDS),
282 params->tls_creds);
283 assert(params->tls_hostname);
284 monitor_printf(mon, "%s: '%s'\n",
285 MigrationParameter_str(MIGRATION_PARAMETER_TLS_HOSTNAME),
286 params->tls_hostname);
287 assert(params->has_max_bandwidth);
288 monitor_printf(mon, "%s: %" PRIu64 " bytes/second\n",
289 MigrationParameter_str(MIGRATION_PARAMETER_MAX_BANDWIDTH),
290 params->max_bandwidth);
291 assert(params->has_avail_switchover_bandwidth);
292 monitor_printf(mon, "%s: %" PRIu64 " bytes/second\n",
293 MigrationParameter_str(MIGRATION_PARAMETER_AVAIL_SWITCHOVER_BANDWIDTH),
294 params->avail_switchover_bandwidth);
295 assert(params->has_downtime_limit);
296 monitor_printf(mon, "%s: %" PRIu64 " ms\n",
297 MigrationParameter_str(MIGRATION_PARAMETER_DOWNTIME_LIMIT),
298 params->downtime_limit);
299 assert(params->has_x_checkpoint_delay);
300 monitor_printf(mon, "%s: %u ms\n",
301 MigrationParameter_str(MIGRATION_PARAMETER_X_CHECKPOINT_DELAY),
302 params->x_checkpoint_delay);
303 monitor_printf(mon, "%s: %u\n",
304 MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_CHANNELS),
305 params->multifd_channels);
306 monitor_printf(mon, "%s: %s\n",
307 MigrationParameter_str(MIGRATION_PARAMETER_MULTIFD_COMPRESSION),
308 MultiFDCompression_str(params->multifd_compression));
309 assert(params->has_zero_page_detection);
310 monitor_printf(mon, "%s: %s\n",
311 MigrationParameter_str(MIGRATION_PARAMETER_ZERO_PAGE_DETECTION),
312 qapi_enum_lookup(&ZeroPageDetection_lookup,
313 params->zero_page_detection));
314 monitor_printf(mon, "%s: %" PRIu64 " bytes\n",
315 MigrationParameter_str(MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE),
316 params->xbzrle_cache_size);
317 monitor_printf(mon, "%s: %" PRIu64 "\n",
318 MigrationParameter_str(MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH),
319 params->max_postcopy_bandwidth);
320 monitor_printf(mon, "%s: '%s'\n",
321 MigrationParameter_str(MIGRATION_PARAMETER_TLS_AUTHZ),
322 params->tls_authz);
323
324 if (params->has_block_bitmap_mapping) {
325 const BitmapMigrationNodeAliasList *bmnal;
326
327 monitor_printf(mon, "%s:\n",
328 MigrationParameter_str(
329 MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING));
330
331 for (bmnal = params->block_bitmap_mapping;
332 bmnal;
333 bmnal = bmnal->next)
334 {
335 const BitmapMigrationNodeAlias *bmna = bmnal->value;
336 const BitmapMigrationBitmapAliasList *bmbal;
337
338 monitor_printf(mon, " '%s' -> '%s'\n",
339 bmna->node_name, bmna->alias);
340
341 for (bmbal = bmna->bitmaps; bmbal; bmbal = bmbal->next) {
342 const BitmapMigrationBitmapAlias *bmba = bmbal->value;
343
344 monitor_printf(mon, " '%s' -> '%s'\n",
345 bmba->name, bmba->alias);
346 }
347 }
348 }
349
350 monitor_printf(mon, "%s: %" PRIu64 " ms\n",
351 MigrationParameter_str(MIGRATION_PARAMETER_X_VCPU_DIRTY_LIMIT_PERIOD),
352 params->x_vcpu_dirty_limit_period);
353
354 monitor_printf(mon, "%s: %" PRIu64 " MB/s\n",
355 MigrationParameter_str(MIGRATION_PARAMETER_VCPU_DIRTY_LIMIT),
356 params->vcpu_dirty_limit);
357
358 assert(params->has_mode);
359 monitor_printf(mon, "%s: %s\n",
360 MigrationParameter_str(MIGRATION_PARAMETER_MODE),
361 qapi_enum_lookup(&MigMode_lookup, params->mode));
362
363 if (params->has_direct_io) {
364 monitor_printf(mon, "%s: %s\n",
365 MigrationParameter_str(
366 MIGRATION_PARAMETER_DIRECT_IO),
367 params->direct_io ? "on" : "off");
368 }
369 }
370
371 qapi_free_MigrationParameters(params);
372 }
373
hmp_loadvm(Monitor * mon,const QDict * qdict)374 void hmp_loadvm(Monitor *mon, const QDict *qdict)
375 {
376 RunState saved_state = runstate_get();
377
378 const char *name = qdict_get_str(qdict, "name");
379 Error *err = NULL;
380
381 vm_stop(RUN_STATE_RESTORE_VM);
382
383 if (load_snapshot(name, NULL, false, NULL, &err)) {
384 load_snapshot_resume(saved_state);
385 }
386
387 hmp_handle_error(mon, err);
388 }
389
hmp_savevm(Monitor * mon,const QDict * qdict)390 void hmp_savevm(Monitor *mon, const QDict *qdict)
391 {
392 Error *err = NULL;
393
394 save_snapshot(qdict_get_try_str(qdict, "name"),
395 true, NULL, false, NULL, &err);
396 hmp_handle_error(mon, err);
397 }
398
hmp_delvm(Monitor * mon,const QDict * qdict)399 void hmp_delvm(Monitor *mon, const QDict *qdict)
400 {
401 Error *err = NULL;
402 const char *name = qdict_get_str(qdict, "name");
403
404 delete_snapshot(name, false, NULL, &err);
405 hmp_handle_error(mon, err);
406 }
407
hmp_migrate_cancel(Monitor * mon,const QDict * qdict)408 void hmp_migrate_cancel(Monitor *mon, const QDict *qdict)
409 {
410 qmp_migrate_cancel(NULL);
411 }
412
hmp_migrate_continue(Monitor * mon,const QDict * qdict)413 void hmp_migrate_continue(Monitor *mon, const QDict *qdict)
414 {
415 Error *err = NULL;
416 const char *state = qdict_get_str(qdict, "state");
417 int val = qapi_enum_parse(&MigrationStatus_lookup, state, -1, &err);
418
419 if (val >= 0) {
420 qmp_migrate_continue(val, &err);
421 }
422
423 hmp_handle_error(mon, err);
424 }
425
hmp_migrate_incoming(Monitor * mon,const QDict * qdict)426 void hmp_migrate_incoming(Monitor *mon, const QDict *qdict)
427 {
428 Error *err = NULL;
429 const char *uri = qdict_get_str(qdict, "uri");
430 MigrationChannelList *caps = NULL;
431 g_autoptr(MigrationChannel) channel = NULL;
432
433 if (!migrate_uri_parse(uri, &channel, &err)) {
434 goto end;
435 }
436 QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel));
437
438 qmp_migrate_incoming(NULL, true, caps, true, false, &err);
439 qapi_free_MigrationChannelList(caps);
440
441 end:
442 hmp_handle_error(mon, err);
443 }
444
hmp_migrate_recover(Monitor * mon,const QDict * qdict)445 void hmp_migrate_recover(Monitor *mon, const QDict *qdict)
446 {
447 Error *err = NULL;
448 const char *uri = qdict_get_str(qdict, "uri");
449
450 qmp_migrate_recover(uri, &err);
451
452 hmp_handle_error(mon, err);
453 }
454
hmp_migrate_pause(Monitor * mon,const QDict * qdict)455 void hmp_migrate_pause(Monitor *mon, const QDict *qdict)
456 {
457 Error *err = NULL;
458
459 qmp_migrate_pause(&err);
460
461 hmp_handle_error(mon, err);
462 }
463
464
hmp_migrate_set_capability(Monitor * mon,const QDict * qdict)465 void hmp_migrate_set_capability(Monitor *mon, const QDict *qdict)
466 {
467 const char *cap = qdict_get_str(qdict, "capability");
468 bool state = qdict_get_bool(qdict, "state");
469 Error *err = NULL;
470 MigrationCapabilityStatusList *caps = NULL;
471 MigrationCapabilityStatus *value;
472 int val;
473
474 val = qapi_enum_parse(&MigrationCapability_lookup, cap, -1, &err);
475 if (val < 0) {
476 goto end;
477 }
478
479 value = g_malloc0(sizeof(*value));
480 value->capability = val;
481 value->state = state;
482 QAPI_LIST_PREPEND(caps, value);
483 qmp_migrate_set_capabilities(caps, &err);
484 qapi_free_MigrationCapabilityStatusList(caps);
485
486 end:
487 hmp_handle_error(mon, err);
488 }
489
hmp_migrate_set_parameter(Monitor * mon,const QDict * qdict)490 void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
491 {
492 const char *param = qdict_get_str(qdict, "parameter");
493 const char *valuestr = qdict_get_str(qdict, "value");
494 Visitor *v = string_input_visitor_new(valuestr);
495 MigrateSetParameters *p = g_new0(MigrateSetParameters, 1);
496 uint64_t valuebw = 0;
497 uint64_t cache_size;
498 Error *err = NULL;
499 int val, ret;
500
501 val = qapi_enum_parse(&MigrationParameter_lookup, param, -1, &err);
502 if (val < 0) {
503 goto cleanup;
504 }
505
506 switch (val) {
507 case MIGRATION_PARAMETER_THROTTLE_TRIGGER_THRESHOLD:
508 p->has_throttle_trigger_threshold = true;
509 visit_type_uint8(v, param, &p->throttle_trigger_threshold, &err);
510 break;
511 case MIGRATION_PARAMETER_CPU_THROTTLE_INITIAL:
512 p->has_cpu_throttle_initial = true;
513 visit_type_uint8(v, param, &p->cpu_throttle_initial, &err);
514 break;
515 case MIGRATION_PARAMETER_CPU_THROTTLE_INCREMENT:
516 p->has_cpu_throttle_increment = true;
517 visit_type_uint8(v, param, &p->cpu_throttle_increment, &err);
518 break;
519 case MIGRATION_PARAMETER_CPU_THROTTLE_TAILSLOW:
520 p->has_cpu_throttle_tailslow = true;
521 visit_type_bool(v, param, &p->cpu_throttle_tailslow, &err);
522 break;
523 case MIGRATION_PARAMETER_MAX_CPU_THROTTLE:
524 p->has_max_cpu_throttle = true;
525 visit_type_uint8(v, param, &p->max_cpu_throttle, &err);
526 break;
527 case MIGRATION_PARAMETER_TLS_CREDS:
528 p->tls_creds = g_new0(StrOrNull, 1);
529 p->tls_creds->type = QTYPE_QSTRING;
530 visit_type_str(v, param, &p->tls_creds->u.s, &err);
531 break;
532 case MIGRATION_PARAMETER_TLS_HOSTNAME:
533 p->tls_hostname = g_new0(StrOrNull, 1);
534 p->tls_hostname->type = QTYPE_QSTRING;
535 visit_type_str(v, param, &p->tls_hostname->u.s, &err);
536 break;
537 case MIGRATION_PARAMETER_TLS_AUTHZ:
538 p->tls_authz = g_new0(StrOrNull, 1);
539 p->tls_authz->type = QTYPE_QSTRING;
540 visit_type_str(v, param, &p->tls_authz->u.s, &err);
541 break;
542 case MIGRATION_PARAMETER_MAX_BANDWIDTH:
543 p->has_max_bandwidth = true;
544 /*
545 * Can't use visit_type_size() here, because it
546 * defaults to Bytes rather than Mebibytes.
547 */
548 ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
549 if (ret < 0 || valuebw > INT64_MAX
550 || (size_t)valuebw != valuebw) {
551 error_setg(&err, "Invalid size %s", valuestr);
552 break;
553 }
554 p->max_bandwidth = valuebw;
555 break;
556 case MIGRATION_PARAMETER_AVAIL_SWITCHOVER_BANDWIDTH:
557 p->has_avail_switchover_bandwidth = true;
558 ret = qemu_strtosz_MiB(valuestr, NULL, &valuebw);
559 if (ret < 0 || valuebw > INT64_MAX
560 || (size_t)valuebw != valuebw) {
561 error_setg(&err, "Invalid size %s", valuestr);
562 break;
563 }
564 p->avail_switchover_bandwidth = valuebw;
565 break;
566 case MIGRATION_PARAMETER_DOWNTIME_LIMIT:
567 p->has_downtime_limit = true;
568 visit_type_size(v, param, &p->downtime_limit, &err);
569 break;
570 case MIGRATION_PARAMETER_X_CHECKPOINT_DELAY:
571 p->has_x_checkpoint_delay = true;
572 visit_type_uint32(v, param, &p->x_checkpoint_delay, &err);
573 break;
574 case MIGRATION_PARAMETER_MULTIFD_CHANNELS:
575 p->has_multifd_channels = true;
576 visit_type_uint8(v, param, &p->multifd_channels, &err);
577 break;
578 case MIGRATION_PARAMETER_MULTIFD_COMPRESSION:
579 p->has_multifd_compression = true;
580 visit_type_MultiFDCompression(v, param, &p->multifd_compression,
581 &err);
582 break;
583 case MIGRATION_PARAMETER_MULTIFD_ZLIB_LEVEL:
584 p->has_multifd_zlib_level = true;
585 visit_type_uint8(v, param, &p->multifd_zlib_level, &err);
586 break;
587 case MIGRATION_PARAMETER_MULTIFD_QATZIP_LEVEL:
588 p->has_multifd_qatzip_level = true;
589 visit_type_uint8(v, param, &p->multifd_qatzip_level, &err);
590 break;
591 case MIGRATION_PARAMETER_MULTIFD_ZSTD_LEVEL:
592 p->has_multifd_zstd_level = true;
593 visit_type_uint8(v, param, &p->multifd_zstd_level, &err);
594 break;
595 case MIGRATION_PARAMETER_ZERO_PAGE_DETECTION:
596 p->has_zero_page_detection = true;
597 visit_type_ZeroPageDetection(v, param, &p->zero_page_detection, &err);
598 break;
599 case MIGRATION_PARAMETER_XBZRLE_CACHE_SIZE:
600 p->has_xbzrle_cache_size = true;
601 if (!visit_type_size(v, param, &cache_size, &err)) {
602 break;
603 }
604 if (cache_size > INT64_MAX || (size_t)cache_size != cache_size) {
605 error_setg(&err, "Invalid size %s", valuestr);
606 break;
607 }
608 p->xbzrle_cache_size = cache_size;
609 break;
610 case MIGRATION_PARAMETER_MAX_POSTCOPY_BANDWIDTH:
611 p->has_max_postcopy_bandwidth = true;
612 visit_type_size(v, param, &p->max_postcopy_bandwidth, &err);
613 break;
614 case MIGRATION_PARAMETER_ANNOUNCE_INITIAL:
615 p->has_announce_initial = true;
616 visit_type_size(v, param, &p->announce_initial, &err);
617 break;
618 case MIGRATION_PARAMETER_ANNOUNCE_MAX:
619 p->has_announce_max = true;
620 visit_type_size(v, param, &p->announce_max, &err);
621 break;
622 case MIGRATION_PARAMETER_ANNOUNCE_ROUNDS:
623 p->has_announce_rounds = true;
624 visit_type_size(v, param, &p->announce_rounds, &err);
625 break;
626 case MIGRATION_PARAMETER_ANNOUNCE_STEP:
627 p->has_announce_step = true;
628 visit_type_size(v, param, &p->announce_step, &err);
629 break;
630 case MIGRATION_PARAMETER_BLOCK_BITMAP_MAPPING:
631 error_setg(&err, "The block-bitmap-mapping parameter can only be set "
632 "through QMP");
633 break;
634 case MIGRATION_PARAMETER_X_VCPU_DIRTY_LIMIT_PERIOD:
635 p->has_x_vcpu_dirty_limit_period = true;
636 visit_type_size(v, param, &p->x_vcpu_dirty_limit_period, &err);
637 break;
638 case MIGRATION_PARAMETER_VCPU_DIRTY_LIMIT:
639 p->has_vcpu_dirty_limit = true;
640 visit_type_size(v, param, &p->vcpu_dirty_limit, &err);
641 break;
642 case MIGRATION_PARAMETER_MODE:
643 p->has_mode = true;
644 visit_type_MigMode(v, param, &p->mode, &err);
645 break;
646 case MIGRATION_PARAMETER_DIRECT_IO:
647 p->has_direct_io = true;
648 visit_type_bool(v, param, &p->direct_io, &err);
649 break;
650 default:
651 g_assert_not_reached();
652 }
653
654 if (err) {
655 goto cleanup;
656 }
657
658 qmp_migrate_set_parameters(p, &err);
659
660 cleanup:
661 qapi_free_MigrateSetParameters(p);
662 visit_free(v);
663 hmp_handle_error(mon, err);
664 }
665
hmp_migrate_start_postcopy(Monitor * mon,const QDict * qdict)666 void hmp_migrate_start_postcopy(Monitor *mon, const QDict *qdict)
667 {
668 Error *err = NULL;
669 qmp_migrate_start_postcopy(&err);
670 hmp_handle_error(mon, err);
671 }
672
673 #ifdef CONFIG_REPLICATION
hmp_x_colo_lost_heartbeat(Monitor * mon,const QDict * qdict)674 void hmp_x_colo_lost_heartbeat(Monitor *mon, const QDict *qdict)
675 {
676 Error *err = NULL;
677
678 qmp_x_colo_lost_heartbeat(&err);
679 hmp_handle_error(mon, err);
680 }
681 #endif
682
683 typedef struct HMPMigrationStatus {
684 QEMUTimer *timer;
685 Monitor *mon;
686 } HMPMigrationStatus;
687
hmp_migrate_status_cb(void * opaque)688 static void hmp_migrate_status_cb(void *opaque)
689 {
690 HMPMigrationStatus *status = opaque;
691 MigrationInfo *info;
692
693 info = qmp_query_migrate(NULL);
694 if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE ||
695 info->status == MIGRATION_STATUS_SETUP) {
696 timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
697 } else {
698 if (info->error_desc) {
699 error_report("%s", info->error_desc);
700 }
701 monitor_resume(status->mon);
702 timer_free(status->timer);
703 g_free(status);
704 }
705
706 qapi_free_MigrationInfo(info);
707 }
708
hmp_migrate(Monitor * mon,const QDict * qdict)709 void hmp_migrate(Monitor *mon, const QDict *qdict)
710 {
711 bool detach = qdict_get_try_bool(qdict, "detach", false);
712 bool resume = qdict_get_try_bool(qdict, "resume", false);
713 const char *uri = qdict_get_str(qdict, "uri");
714 Error *err = NULL;
715 g_autoptr(MigrationChannelList) caps = NULL;
716 g_autoptr(MigrationChannel) channel = NULL;
717
718 if (!migrate_uri_parse(uri, &channel, &err)) {
719 hmp_handle_error(mon, err);
720 return;
721 }
722 QAPI_LIST_PREPEND(caps, g_steal_pointer(&channel));
723
724 qmp_migrate(NULL, true, caps, false, false, true, resume, &err);
725 if (hmp_handle_error(mon, err)) {
726 return;
727 }
728
729 if (!detach) {
730 HMPMigrationStatus *status;
731
732 if (monitor_suspend(mon) < 0) {
733 monitor_printf(mon, "terminal does not allow synchronous "
734 "migration, continuing detached\n");
735 return;
736 }
737
738 status = g_malloc0(sizeof(*status));
739 status->mon = mon;
740 status->timer = timer_new_ms(QEMU_CLOCK_REALTIME, hmp_migrate_status_cb,
741 status);
742 timer_mod(status->timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME));
743 }
744 }
745
migrate_set_capability_completion(ReadLineState * rs,int nb_args,const char * str)746 void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
747 const char *str)
748 {
749 size_t len;
750
751 len = strlen(str);
752 readline_set_completion_index(rs, len);
753 if (nb_args == 2) {
754 int i;
755 for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
756 readline_add_completion_of(rs, str, MigrationCapability_str(i));
757 }
758 } else if (nb_args == 3) {
759 readline_add_completion_of(rs, str, "on");
760 readline_add_completion_of(rs, str, "off");
761 }
762 }
763
migrate_set_parameter_completion(ReadLineState * rs,int nb_args,const char * str)764 void migrate_set_parameter_completion(ReadLineState *rs, int nb_args,
765 const char *str)
766 {
767 size_t len;
768
769 len = strlen(str);
770 readline_set_completion_index(rs, len);
771 if (nb_args == 2) {
772 int i;
773 for (i = 0; i < MIGRATION_PARAMETER__MAX; i++) {
774 readline_add_completion_of(rs, str, MigrationParameter_str(i));
775 }
776 }
777 }
778
vm_completion(ReadLineState * rs,const char * str)779 static void vm_completion(ReadLineState *rs, const char *str)
780 {
781 size_t len;
782 BlockDriverState *bs;
783 BdrvNextIterator it;
784
785 GRAPH_RDLOCK_GUARD_MAINLOOP();
786
787 len = strlen(str);
788 readline_set_completion_index(rs, len);
789
790 for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
791 SnapshotInfoList *snapshots, *snapshot;
792 bool ok = false;
793
794 if (bdrv_can_snapshot(bs)) {
795 ok = bdrv_query_snapshot_info_list(bs, &snapshots, NULL) == 0;
796 }
797 if (!ok) {
798 continue;
799 }
800
801 snapshot = snapshots;
802 while (snapshot) {
803 readline_add_completion_of(rs, str, snapshot->value->name);
804 readline_add_completion_of(rs, str, snapshot->value->id);
805 snapshot = snapshot->next;
806 }
807 qapi_free_SnapshotInfoList(snapshots);
808 }
809
810 }
811
delvm_completion(ReadLineState * rs,int nb_args,const char * str)812 void delvm_completion(ReadLineState *rs, int nb_args, const char *str)
813 {
814 if (nb_args == 2) {
815 vm_completion(rs, str);
816 }
817 }
818
loadvm_completion(ReadLineState * rs,int nb_args,const char * str)819 void loadvm_completion(ReadLineState *rs, int nb_args, const char *str)
820 {
821 if (nb_args == 2) {
822 vm_completion(rs, str);
823 }
824 }
825