migration: Initial support of fixed-ram feature for analyze-migration.py
In order to allow analyze-migration.py script to work with migration streams that have the 'fixed-ram' capability set it's required to have access to the stream's configuration object. This commit enables this by making migration json writer part of MigrationState struct, allowing the configuration object be serialized to json. Signed-off-by: Nikolay Borisov <nborisov@suse.com>
This commit is contained in:
committed by
Fabiano Rosas
parent
3ce4e2e8d5
commit
ea1efd3d17
@@ -2260,6 +2260,7 @@ void migrate_init(MigrationState *s)
|
|||||||
error_free(s->error);
|
error_free(s->error);
|
||||||
s->error = NULL;
|
s->error = NULL;
|
||||||
s->hostname = NULL;
|
s->hostname = NULL;
|
||||||
|
s->vmdesc = NULL;
|
||||||
|
|
||||||
migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
|
migrate_set_state(&s->state, MIGRATION_STATUS_NONE, MIGRATION_STATUS_SETUP);
|
||||||
|
|
||||||
|
@@ -1206,13 +1206,25 @@ void qemu_savevm_non_migratable_list(strList **reasons)
|
|||||||
|
|
||||||
void qemu_savevm_state_header(QEMUFile *f)
|
void qemu_savevm_state_header(QEMUFile *f)
|
||||||
{
|
{
|
||||||
|
MigrationState *s = migrate_get_current();
|
||||||
|
|
||||||
|
s->vmdesc = json_writer_new(false);
|
||||||
|
|
||||||
trace_savevm_state_header();
|
trace_savevm_state_header();
|
||||||
qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
|
qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
|
||||||
qemu_put_be32(f, QEMU_VM_FILE_VERSION);
|
qemu_put_be32(f, QEMU_VM_FILE_VERSION);
|
||||||
|
|
||||||
if (migrate_get_current()->send_configuration) {
|
if (s->send_configuration) {
|
||||||
qemu_put_byte(f, QEMU_VM_CONFIGURATION);
|
qemu_put_byte(f, QEMU_VM_CONFIGURATION);
|
||||||
vmstate_save_state(f, &vmstate_configuration, &savevm_state, 0);
|
/*
|
||||||
|
* This starts the main json object and is paired with the
|
||||||
|
* json_writer_end_object in
|
||||||
|
* qemu_savevm_state_complete_precopy_non_iterable
|
||||||
|
*/
|
||||||
|
json_writer_start_object(s->vmdesc, NULL);
|
||||||
|
json_writer_start_object(s->vmdesc, "configuration");
|
||||||
|
vmstate_save_state(f, &vmstate_configuration, &savevm_state, s->vmdesc);
|
||||||
|
json_writer_end_object(s->vmdesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1237,8 +1249,6 @@ void qemu_savevm_state_setup(QEMUFile *f)
|
|||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ms->vmdesc = json_writer_new(false);
|
|
||||||
json_writer_start_object(ms->vmdesc, NULL);
|
|
||||||
json_writer_int64(ms->vmdesc, "page_size", qemu_target_page_size());
|
json_writer_int64(ms->vmdesc, "page_size", qemu_target_page_size());
|
||||||
json_writer_start_array(ms->vmdesc, "devices");
|
json_writer_start_array(ms->vmdesc, "devices");
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@ import argparse
|
|||||||
import collections
|
import collections
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
import math
|
||||||
|
|
||||||
def mkdir_p(path):
|
def mkdir_p(path):
|
||||||
try:
|
try:
|
||||||
@@ -119,11 +119,16 @@ class RamSection(object):
|
|||||||
self.file = file
|
self.file = file
|
||||||
self.section_key = section_key
|
self.section_key = section_key
|
||||||
self.TARGET_PAGE_SIZE = ramargs['page_size']
|
self.TARGET_PAGE_SIZE = ramargs['page_size']
|
||||||
|
self.TARGET_PAGE_BITS = math.log2(self.TARGET_PAGE_SIZE)
|
||||||
self.dump_memory = ramargs['dump_memory']
|
self.dump_memory = ramargs['dump_memory']
|
||||||
self.write_memory = ramargs['write_memory']
|
self.write_memory = ramargs['write_memory']
|
||||||
|
self.fixed_ram = ramargs['fixed-ram']
|
||||||
self.sizeinfo = collections.OrderedDict()
|
self.sizeinfo = collections.OrderedDict()
|
||||||
|
self.bitmap_offset = collections.OrderedDict()
|
||||||
|
self.pages_offset = collections.OrderedDict()
|
||||||
self.data = collections.OrderedDict()
|
self.data = collections.OrderedDict()
|
||||||
self.data['section sizes'] = self.sizeinfo
|
self.data['section sizes'] = self.sizeinfo
|
||||||
|
self.ram_read = False
|
||||||
self.name = ''
|
self.name = ''
|
||||||
if self.write_memory:
|
if self.write_memory:
|
||||||
self.files = { }
|
self.files = { }
|
||||||
@@ -140,7 +145,13 @@ class RamSection(object):
|
|||||||
def getDict(self):
|
def getDict(self):
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
|
def write_or_dump_fixed_ram(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
|
if self.fixed_ram and self.ram_read:
|
||||||
|
return
|
||||||
|
|
||||||
# Read all RAM sections
|
# Read all RAM sections
|
||||||
while True:
|
while True:
|
||||||
addr = self.file.read64()
|
addr = self.file.read64()
|
||||||
@@ -167,7 +178,26 @@ class RamSection(object):
|
|||||||
f.truncate(0)
|
f.truncate(0)
|
||||||
f.truncate(len)
|
f.truncate(len)
|
||||||
self.files[self.name] = f
|
self.files[self.name] = f
|
||||||
|
|
||||||
|
if self.fixed_ram:
|
||||||
|
bitmap_len = self.file.read32()
|
||||||
|
# skip the pages_offset which we don't need
|
||||||
|
offset = self.file.tell() + 8
|
||||||
|
self.bitmap_offset[self.name] = offset
|
||||||
|
offset = ((offset + bitmap_len + self.TARGET_PAGE_SIZE - 1) //
|
||||||
|
self.TARGET_PAGE_SIZE) * self.TARGET_PAGE_SIZE
|
||||||
|
self.pages_offset[self.name] = offset
|
||||||
|
self.file.file.seek(offset + len)
|
||||||
|
|
||||||
flags &= ~self.RAM_SAVE_FLAG_MEM_SIZE
|
flags &= ~self.RAM_SAVE_FLAG_MEM_SIZE
|
||||||
|
if self.fixed_ram:
|
||||||
|
self.ram_read = True
|
||||||
|
# now we should rewind to the ram page offset of the first
|
||||||
|
# ram section
|
||||||
|
if self.fixed_ram:
|
||||||
|
if self.write_memory or self.dump_memory:
|
||||||
|
self.write_or_dump_fixed_ram()
|
||||||
|
return
|
||||||
|
|
||||||
if flags & self.RAM_SAVE_FLAG_COMPRESS:
|
if flags & self.RAM_SAVE_FLAG_COMPRESS:
|
||||||
if flags & self.RAM_SAVE_FLAG_CONTINUE:
|
if flags & self.RAM_SAVE_FLAG_CONTINUE:
|
||||||
@@ -208,7 +238,7 @@ class RamSection(object):
|
|||||||
|
|
||||||
# End of RAM section
|
# End of RAM section
|
||||||
if flags & self.RAM_SAVE_FLAG_EOS:
|
if flags & self.RAM_SAVE_FLAG_EOS:
|
||||||
break
|
return
|
||||||
|
|
||||||
if flags != 0:
|
if flags != 0:
|
||||||
raise Exception("Unknown RAM flags: %x" % flags)
|
raise Exception("Unknown RAM flags: %x" % flags)
|
||||||
@@ -521,6 +551,7 @@ class MigrationDump(object):
|
|||||||
ramargs['page_size'] = self.vmsd_desc['page_size']
|
ramargs['page_size'] = self.vmsd_desc['page_size']
|
||||||
ramargs['dump_memory'] = dump_memory
|
ramargs['dump_memory'] = dump_memory
|
||||||
ramargs['write_memory'] = write_memory
|
ramargs['write_memory'] = write_memory
|
||||||
|
ramargs['fixed-ram'] = False
|
||||||
self.section_classes[('ram',0)][1] = ramargs
|
self.section_classes[('ram',0)][1] = ramargs
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -528,8 +559,20 @@ class MigrationDump(object):
|
|||||||
if section_type == self.QEMU_VM_EOF:
|
if section_type == self.QEMU_VM_EOF:
|
||||||
break
|
break
|
||||||
elif section_type == self.QEMU_VM_CONFIGURATION:
|
elif section_type == self.QEMU_VM_CONFIGURATION:
|
||||||
section = ConfigurationSection(file)
|
config_desc = self.vmsd_desc.get('configuration')
|
||||||
section.read()
|
if config_desc is not None:
|
||||||
|
config = VMSDSection(file, 1, config_desc, 'configuration')
|
||||||
|
config.read()
|
||||||
|
caps = config.data.get("configuration/capabilities")
|
||||||
|
if caps is not None:
|
||||||
|
caps = caps.data["capabilities"]
|
||||||
|
if type(caps) != list:
|
||||||
|
caps = [caps]
|
||||||
|
for i in caps:
|
||||||
|
# chomp out string length
|
||||||
|
cap = i.data[1:].decode("utf8")
|
||||||
|
if cap == "fixed-ram":
|
||||||
|
ramargs['fixed-ram'] = True
|
||||||
elif section_type == self.QEMU_VM_SECTION_START or section_type == self.QEMU_VM_SECTION_FULL:
|
elif section_type == self.QEMU_VM_SECTION_START or section_type == self.QEMU_VM_SECTION_FULL:
|
||||||
section_id = file.read32()
|
section_id = file.read32()
|
||||||
name = file.readstr()
|
name = file.readstr()
|
||||||
|
Reference in New Issue
Block a user